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 <pedzsan@gmail.com> 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