GCC __cxa_atexit

From Apache OpenOffice Wiki
Jump to: navigation, search


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 and atexit 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 register atexit 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 and atexit handlers (from within a single run-time object) is wrong (the below code issues two lines of f 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 and atexit handlers (from within a single run-time object) is correct (the below code issues two sets of lines ~C and f in such a case).
  • In any event, GCC calls static object destructors and atexit handlers from a shared object during its final dlclose call, or during exit (if there is no final dlclose call). (The C++ Standard would require that static object destructors and atexit handlers are called during exit, 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;
Personal tools