G++: Order of static destructors ?

Nick Clifton nickc@redhat.com
Mon Feb 13 07:51:00 GMT 2006


Hi Guys,

  There appears to be a discrepancy in the way that G++ orders its
  static destructors.  Given this test program:

#include <iostream>
using namespace std;

class A 
{
public:
    int     i;
    A(int j) : i(j) { cout << "constructor A" << endl; }
    ~A() { cout << "destructor A : i = " << i << endl; }
};

class B 
{
public:
    A *n;
    B() {
        static A p(1);
        n = &p;
        cout << "constructor B" << endl;
    }
    ~B() {
        cout << "destructor B : i = " << n->i << endl;
        n->i = 10;
    }
};

class B x1;

int main (void) { return 0; }

  When compiled and run using an x86_64 native gcc built from today's
  sources this program will produce this output:
  
constructor A
constructor B
destructor A : i = 1
destructor B : i = 1

  However when compiled using a 3.4.4 native x86_64 compiler the
  following is produced when the program is run:
  
constructor A
constructor B
destructor B : i = 1
destructor A : i = 10

  Looking at what I hope is the right part of the C++ language
  specification:

3.6.3 - Termination [basic.start.term]
-1- Destructors (class.dtor) for initialized objects of static storage duration 
(declared at block scope or at namespace scope) are called as a result of 
returning from main and as a result of calling exit (lib.support.start.term). 
These objects are destroyed in the reverse order of the completion of their 
constructor or of the completion of their dynamic initialization. If an object 
is initialized statically, the object is destroyed in the same order as if the 
object was dynamically initialized. For an object of array or class type, all 
subobjects of that object are destroyed before any local object with static 
storage duration initialized during the construction of the subobjects is 
destroyed.

  This appears to state that the 3.4.4 compiler got it right.

  The problem I believe is that the destructor for class A is
  registered to run using atexit() when the constructor for class B is
  run, but the destructor for class B is permanently recorded in the
  .dtors section.  Since the exit() function runs the things recorded
  with atexit() first, before calling _exit() which runs the
  destructors in the .dtors section, the destructor for A is called
  before the destructor for B.

  Can anyone clarify this for me ?  Is this a bug with the current G++
  implementation ?

Cheers
  Nick
  



More information about the Gcc-bugs mailing list