GCC __cxa_atexit
From Apache OpenOffice Wiki
The thing with GCC --enable-__cxa_atexit
appears to be as follows:
- Section 3.3.5 DSO Object Destruction API of the Itanium C++ ABI (at least in revision 1.86; despite its name, this is the ABI GCC generally uses for quite a while now) defines
__cxa_atexit
, to register static object destructors andatexit
handlers. - On Linux,
__cxa_atexit
is available at least since glibc 2.2.4. - At least until GCC 4.0.3, if GCC is not explicitly configured with
--enable-__cxa_atexit
, it does not use__cxa_atexit
to register static object destructors (but at least on Linux with a glibc that has__cxa_atexit
, it nonetheless does use it to registeratexit
handlers). - At least since GCC 4.2, GCC no longer needs to be explicitly configured with
--enable-__cxa_atexit
—whether or not__cxa_atexit
is used to register static object destructors is apparently decided based on the available features of the system. - If GCC does not use
__cxa_atexit
to register static object destructors, it violates the C++ Standard in that the relative order of calls of static object destructors andatexit
handlers (from within a single run-time object) is wrong (the below code issues two lines off
followed by two lines of~C
in such a case). Conversely, if GCC does use__cxa_atexit
to register static object destructors, it conforms to the C++ Standard in that the relative order of the calls of static object destructors andatexit
handlers (from within a single run-time object) is correct (the below code issues two sets of lines~C
andf
in such a case). - In any event, GCC calls static object destructors and
atexit
handlers from a shared object during its finaldlclose
call, or duringexit
(if there is no finaldlclose
call). (The C++ Standard would require that static object destructors andatexit
handlers are called duringexit
, but does not cater for the needs of shared objects.) - The (slightly patched) GCC 3.4.1 used in the Sun Hamburg
setsolar
environment is configured without--enable-__cxa_atexit
(and thus does not use__cxa_atexit
to register static object destructors), although the OOo baseline would allow otherwise. (The reason appears to be unknown, it is probably simply that nobody knew the swith needed to be set explicitly.)
Some test code:
-- Makefile all: main dl.so main: main.cc g++ -o $@ -ldl $^ dl.so: dl.cc g++ -shared -o $@ $^ -- main.cc #include <cstdlib> #include <iostream> #include <dlfcn.h> int main() { void * h = dlopen("./dl.so", RTLD_LOCAL | RTLD_LAZY); if (h == NULL) std::abort(); std::cout << "before dlclose\n"; if (dlclose(h) != 0) std::abort(); std::cout << "before exit\n"; } -- dl.cc #include <cstdlib> #include <iostream> extern "C" void f() { std::cout << "f\n"; } struct C { C() { if (std::atexit(&f) != 0) std::abort(); } ~C() { std::cout << "~C\n"; } }; static C s1, s2;