This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
optimization/5841: c++ error with order of ctors/dtors
- From: Rasmus Hahn <rassahah at infonie dot de>
- To: gcc-gnats at gcc dot gnu dot org
- Cc: rassahah at infonie dot de
- Date: Tue, 5 Mar 2002 20:20:02 +0100
- Subject: optimization/5841: c++ error with order of ctors/dtors
- Reply-to: rassahah at infonie dot de
>Number: 5841
>Category: optimization
>Synopsis: g++ calls ctors/dtors in wrong order
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: unassigned
>State: open
>Class: wrong-code
>Submitter-Id: net
>Arrival-Date: Tue Mar 05 11:26:00 PST 2002
>Closed-Date:
>Last-Modified:
>Originator: Rasmus Hahn
>Release: 3.0.4
>Organization:
Infonie GmBH
>Environment:
System: Linux hamburg 2.4.16 #9 Fri Jan 11 14:51:00 CET 2002 i686 unknown
Architecture: i686
host: i686-pc-linux-gnu
build: i686-pc-linux-gnu
target: i686-pc-linux-gnu
configured with: ../configure --prefix=/usr --infodir=/usr/share/info --mandir=/usr/share/man --enable-threads
>Description:
The problem occurs only with c++ and optimization turned on
(at least -O and -O2). G++ seems to allocate sometimes the same space
for some temporary c++-Objects on the stack. But with optimization switch
on, it looks like that all destructor calls go to the end of a compilation
unit, not after the temporary object becomes unused. For objects which
share the same memory the constructors are called first, and then all
the destructors. That is of course not correct. However this is of course
not always the case just for some szenarios. I extracted a short example
(included) from a larger project showing the effect. In the example i used
printf to document the wrong behaviour, so dont be disappointed when
it doesnt crash with segmentation fault as you might hope. In a bigger
application it likely will, i suspect. Program output (for your pleasure):
without -O: with -O:
constructed 0xbffff9b4 constructed 0xbffff9b4
constructed 0xbffff984 constructed 0xbffff994
0xbffff984 destructed constructed 0xbffff9a4
constructed 0xbffff9a4 constructed 0xbffff994
constructed 0xbffff984 0xbffff994 destructed
0xbffff984 destructed 0xbffff9a4 destructed
0xbffff9a4 destructed error, deleted twice, should never be the case
0xbffff9b4 destructed 0xbffff994 destructed
0xbffff9b4 destructed
As one might see, the number of addresses for which constructors and
destructors called are the same, just the order differs. 0xbffff994
on the right side is constructed twice, thereafter destructed twice.
Using -fno-default-inline also does not show the error. I did not
check if this bug is in CVS-version of gcc too, but it is in 3.0
up to 3.0.4 and by induction follows it is.
I had no idea of the priority of this error, so i set it to 'medium'.
Greetings - Rasmus
>How-To-Repeat:
/*
* this code uses two classes to reproduce the error. This seems to
* be necessary. I was not able to get the wrong behaviour with one class
* but that doesnt mean its not possible. To be shure where the error
* is located i do not #inlude anything but declared printf by hand.
* The problem occurred originally in some completely other context
* so it should not depend on that.
*/
extern "C" {
int printf (const char *, ...);
}
class Double;
struct Integer {
/*
* living is set by constructor, reset by destructor
* so it should never be 0 at start of destructor.
*/
int living;
/* some constructors... */
Integer (const Double &d) {
living = 1;
printf ("constructed %p\n", this);
}
Integer (int i) {
living = 1;
printf ("constructed %p\n", this);
}
Integer (const Integer &ref) {
living = 1;
printf ("constructed %p\n", this);
}
~Integer () {
if (living != 1)
printf ("error, deleted twice, should never be the case\n");
living = 0;
printf ("%p destructed\n", this);
}
};
struct Double {
Double (Integer i) {}
};
void plus (Integer a, Integer b) { }
int main () {
Integer one (1);
plus (Integer (Double (one)),one);
}
>Fix:
dont use optimization
or: use -fno-default-inline -fno-inline when using optimization
or: Dont use temporary objects on the stack with optimization
(often not an option)
or: Dont write c++-programs with more than one class
(not an option for OO-Gurus)
>Release-Note:
>Audit-Trail:
>Unformatted: