🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.std.c++
Article #2525

Re: Global Init/Shutdown: A solution (hopefully)

#2525
From: Fergus Henderson
Date: Sat, 11 Nov 1995 08:25
79 lines
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. ]
Technical Details
Message-ID: <9531518.10407@mulga.cs.mu.OZ.AU>
Path: arc1-ca.pugleaf.net!in1.uu.net!bounce-back
References: <199511110341.UAA26529@ncar.ucar.EDU>

Show Full Headers
Complete Article Headers
Approved: fjh@cs.mu.oz.au
Date: 11 Nov 95 08:25:25 GMT
From: fjh@munta.cs.mu.OZ.AU (Fergus Henderson)
Message-ID: <9531518.10407@mulga.cs.mu.OZ.AU>
Newsgroups: comp.std.c++
Organization: Computer Science, University of Melbourne, Australia
Path: arc1-ca.pugleaf.net!in1.uu.net!bounce-back
References: <199511110341.UAA26529@ncar.ucar.EDU>
Subject: Re: Global Init/Shutdown: A solution (hopefully)
X-Auth: PGPMoose V1.1 PGP comp.std.c++
 iQBFAgUBMKReCOEDnX0m9pzZAQEsWwF/baaLzH3U2FbZZ0n0d4RnH9wnyOaJnVe8
 uW1/T1Ew4Ym4MLj4jhXP6TIxha7EqiGP
 =GUw9