On Aug 5, 2012, at 3:50 PM, Perry Smith wrote: > > On Aug 5, 2012, at 1:09 PM, David Edelsohn wrote: > >> On Sun, Aug 5, 2012 at 9:56 AM, Perry Smith <[email protected]> wrote: >> >>> I was planning on exploring when _GLOBAL__FD was called today. I >>> need to figure out when gcc puts the call to the dtor in _GLOBAL__FD >>> path rather than in the atexit path. The net implies that "static" uses >>> atexit while a global non-static uses _GLOBAL__FD >>> >>> I'm also exploring what it would take to port a version of GNU's >>> __cxa_atexit to AIX. I think after I figure out when various dtors >>> get called, I should be able to figure out if / how to do that. >>> >>> Part of my confusion / concern is "why have two methods?" >>> Does the spec say that dtors much be called at different times? >> >> Destructors are added to _GLOBAL__FD by collect2 at link time. It >> scans the object files for destructor functions, sorts them by >> priority and creates a function connected to _GLOBAL__FD to call them. >> Collect2 performs the same grouping for constructors, creates a >> function and connects it to _GLOBAL__FI. The uniquely named functions >> are added to the AIX linker command line as arguments to the >> -binitfini option to establish them as initializer/finalizer functions >> for the shared object. >> >> AIX does not have a ctor/dtor or init/fini section in object files, >> nor _cxa_atexit. >> >> AIX dlclose() should call AIX terminateAndUnload() service that will >> call the fini routine registered by -binitfini. If something else in >> GCC is trying to register the termination function for systems without >> _cxa_atexit() using atexit(), it probably is conflicting and trying to >> run the destructors twice. >> >> Another difference between AIX and SVR4 is AIX invokes init and fini >> functions for multiple, dependent shared objects breadth first, while >> SVR4 invokes them depth first based on library dependencies. There is >> an old Bugzilla entry with a proposal to push init functions onto a >> stack as they are seen when libraries are loaded and then run them in >> SVR4 dependency order. > > Thank you both for helping. > > I understand when atexit is used. I believe the _GLOBAL__FD method > could be used instead and would be more correct but it somehow needs to > be conditionalized. > > To get the atexit to be used, you need a function that returns a static > that is declared inside the function. In my code below, this is > "func". > > The function registered with atexit is called tcf_0 (I'm sure that > would increment if there are more than one). I mention that hoping it > might help in tracking down where it is being created. > > There are other parts to this program that I left because, to me, it > was interesting when atexit is called and all the places where it is > not called. > > I call the program x1.cpp. x1 with no argument does not create > "func". x1 with an argument does. Note that if func is not created, > the dtor is not called (which seems obvoius but that is where the > difficulty is going to come from). > > My thoughts on how to solve this would call tcf_0 from the _GLOBAL_FD > and have tcf_0 check a flag. If not set, it does nothing. In the > special ctor where atexit is now being called, just set that flag > instead of calling atexit. > > Here is the program: > > #include <iostream> > using namespace std; > > class foo { > private: > const char *name; > void mess(const char *s) { > cout << s << " " << name << endl; > } > > public: > foo(const char *s) { > name = s; > mess("ctor"); > } > > ~foo() { > mess("dtor"); > } > }; > > class bar { > static foo surf; > }; > foo bar::surf("bar"); > > foo g("global"); > static foo s("static"); > > foo& func() > { > static foo val("func"); > return val; > } > > int main (int argc, char *argv[]) > { > cout << "Hello World!" << endl; > foo a("auto"); > > if (argc > 1) > foo &f = func(); > > cout << "Good Bye World!" << endl; > return 0; > } > > Output with x1 called with no argument: > ctor bar > ctor global > ctor static > Hello World! > ctor auto > Good Bye World! > dtor auto > dtor static > dtor global > dtor bar > > Output with x1 called with an argument: > ctor bar > ctor global > ctor static > Hello World! > ctor auto > ctor func << atexit called just after this prints. > Good Bye World! > dtor auto > dtor func > dtor static > dtor global > dtor bar > > I'm happy to create a bug report if anyone wants me to.
Not sure why this thread died. I've been looking at the code trying to gain the courage to try and implement the changes I suggested but was also waiting to hear back from others. Thank you, Perry
