Thread View: comp.std.c++
3 messages
3 total messages
Started by JdeBP
Sat, 11 Nov 1995 06:06
Re: Global Init/Shutdown: A solution (hopefully)
Author: JdeBP
Date: Sat, 11 Nov 1995 06:06
Date: Sat, 11 Nov 1995 06:06
48 lines
1902 bytes
1902 bytes
Further to the global initialisation/cleanup discussion, can anyone tell me
when `woggle::~woggle' is called in the following program ? Is undefined
behaviour invoked ?
If you think that the program is non-conforming (aside from any
typographical mistakes that I make, which I'm sure that you'll overlook in
view of the latesness of the hour, and the fact that I'm typing this in by
hand) please explain where and why it is non-conforming.
//
// **************************************************************
// WOGGLE -- Jonathan de Boyne Pollard 19951111
// **************************************************************
//
#include <stdlib.h>
class woggle {
public:
char * p ;
woggle() p(new(nothrow()) char) {}
~woggle() { char * q = p ; p = 0 ; delete q ; }
} ;
void *
std::operator new ( size_t s, const std::nothrow & ) throw()
{
return malloc(s) ;
}
void
std::operator delete ( void * p ) throw()
{
static woggle w ;
*w.p = ' ' ;
free(p) ;
}
int
main ( int, char ** )
{
delete new(nothrow()) char ;
return EXIT_SUCCESS ;
}
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Re: Global Init/Shutdown: A solution (hopefully)
Author: Fergus Henderson
Date: Sat, 11 Nov 1995 08:25
Date: Sat, 11 Nov 1995 08:25
79 lines
3164 bytes
3164 bytes
JdeBP@jba.co.uk writes:
>Further to the global initialisation/cleanup discussion, can anyone tell me
>when `woggle::~woggle' is called in the following program ? Is undefined
>behaviour invoked ?
>#include <stdlib.h>
>
>class woggle {
>public:
> char * p ;
> woggle() p(new(nothrow()) char) {}
> ~woggle() { char * q = p ; p = 0 ; delete q ; }
>} ;
>
>void *
>std::operator new ( size_t s, const std::nothrow & ) throw()
>{
> return malloc(s) ;
>}
As discussed here recently, `operator new' should be defined in the
global namespace, as specified by 3.7.3. Your program violates
17.3.3.1/1 "a program shall not extend the namespace `std'".
>void
>std::operator delete ( void * p ) throw()
>{
> static woggle w ;
> *w.p = ' ' ;
> free(p) ;
>}
Even if this were defined in the global namespace, there would
still be a problem. You didn't replace `operator new(size_t)', so
there is no guarantee that objects passed to your replacement for
`operator delete' will have been allocated with `malloc()'.
>int
>main ( int, char ** )
>{
> delete new(nothrow()) char ;
> return EXIT_SUCCESS ;
>}
If we ignore the two problem noted above, there is still at least
one more problem.
Lets see... there are no user-defined global objects or static members
with constructors, so after execution of the constructors for library
objects such as `cin' and `cout', execution begins in main().
First we execute `new(nothrow()) char', which invokes `operator new (1,
nothrow())', which returns the result of `malloc(1)'.
Then we execute `delete' on the resulting `char *' pointer,
which invokes your `operator delete(void *)'.
One entry to your `operator delete', the constructor for `static woggle w'
gets executed. This initializes `w.p' with `new (nothrow()) char',
which as before returns the result of `malloc(1)'.
Then the code
*w.p = ' ' ;
free(p) ;
is executed to complete the execution of `operator delete'.
Finally, on exit from main(), the desctructor for `w' will be called.
Oops, undefined behaviour:
~woggle() { char * q = p ; p = 0 ; delete q ; }
^^^^^
Here `w.p' has already been deallocated, so any attempt to even
just copy the invalidated pointer it is undefined behaviour.
--
Fergus Henderson WWW: http://www.cs.mu.oz.au/~fjh
fjh@cs.mu.oz.au PGP: finger fjh@128.250.37.3
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Re: Global Init/Shutdown: A solution (hopefully)
Author: J. Kanze
Date: Mon, 13 Nov 1995 13:04
Date: Mon, 13 Nov 1995 13:04
66 lines
3962 bytes
3962 bytes
JdeBP@jba.co.uk wrote:
|> Further to the global initialisation/cleanup discussion, can anyone tell me
|> when `woggle::~woggle' is called in the following program ? Is undefined
|> behaviour invoked ?
|> If you think that the program is non-conforming (aside from any
|> typographical mistakes that I make, which I'm sure that you'll overlook in
|> view of the latesness of the hour, and the fact that I'm typing this in by
|> hand) please explain where and why it is non-conforming.
Fergus Henderson has done this, but IMHO, he didn't address the real
problem I think you are trying to raise.
The problem is *not* unique to operator delete: in general, it can occur
in any function called from the destructor of a static object that
contains a static object.
In general, static objects will *not* work in functions called from the
destructors of other static objects *unless* the same function was
called during the constructor (or before). I believe that this is
implicit in the standard, in section 3.6.3, which states that static
objects will be destructed in the reverse order of there construction.
For a given static object, x, any local static objects in functions
called by the destructor will have already been destructed unless the
function was called (and the local static object constructed) *before*
the construction of x.
There are at least two open points in my mind:
1. When should a local static object be destructed if the block
containing it is first executed in the destructor of a static object? A
(too) literal interpretation of the current wording would suggest that
it must be destructed *before* destructing the object which triggered
its construction, since it was certainly constructed after that object.
2. When is construction considered to take place for the purpose of this
ordering. In particular:
class A { A() {} } ;
class B { B() { static A a ; } } ;
B b ;
Which should be destructed first, the local static in B::B(), or the
global? (The constructor of the global encompasses that of the local.
Ordering by start of the constructor gives: b, a; by finish of the
constructor a, b.)
The easiest solution for the committee would be probably be to just
change the wording in 3.6.3 to say that all nonlocal statics are
destructed, in the reverse order of their construction, then all local
statics, in an undefined order. (And perhaps add a mention that statics
that have not been constructed will *not* be destructed. Although I
would consider this just common sense, we have to consider that the
standard may be read and interpreted by people without common sense.)
This is also a fairly simple rule to implement (I think: comments from
implementers...). Can anyone think of any situations where it will
cause problems for the users?
--
James Kanze (+33) 88 14 49 00 email: kanze@gabi-soft.fr
GABI Software, Sarl., 8 rue des Francs Bourgeois, 67000 Strasbourg, France
Conseils, itudes et rialisations en logiciel orienti objet --
-- A la recherche d'une activiti dans une region francophone
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads