This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

optimization/5841: c++ error with order of ctors/dtors



>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:


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]