__cxa_atexit() 和 atexit() 有什么区别

What is the difference between __cxa_atexit() and atexit()

GCC docs 中,我找到了 -fuse-cxa-atexit 选项,它表示如下:

This option is required for fully standards-compliant handling of static destructors

那么两者有什么区别呢?在 __cxa_atexit 的文档中,我发现了以下内容:

The __cxa_atexit() function is used to implement atexit()

我正在函数中实现静态(不要问为什么),我想知道使用 2 中的哪一个来调用析构函数。

而且我想我只有 atexit() 用于 MSVC?有问题吗?

我可以只在任何地方使用 atexit() 并确保它的行为就像函数中的真实静态对象一样吗?

__cxa_atexit() 在 Itanium C++ ABI 中定义。该文件解释了 motivation behind this function:

The C++ Standard requires that destructors be called for global objects when a program exits in the opposite order of construction. Most implementations have handled this by calling the C library atexit routine to register the destructors. This is problematic because the 1999 C Standard only requires that the implementation support 32 registered functions, although most implementations support many more. More important, it does not deal at all with the ability in most implementations to remove [Dynamic Shared Objects] from a running program image by calling dlclose prior to program termination.

The API specified below is intended to provide standard-conforming treatment during normal program exit, which includes executing atexit-registered functions in the correct sequence relative to constructor-registered destructors, and reasonable treatment during early DSO unload (e.g. dlclose).

所以:

  • __cxa_atexit()不限32个函数
  • __cxa_atexit()会在程序退出前卸载动态库时调用动态库的static的析构函数

如果您正在编写一个库,您应该启用-fuse-cxa-atexit,并且您的 libc 具有此功能(例如 glibc、musl)。事实上,你的发行版附带的 gcc 可能已经自动启用了这个标志(如果你启用了这个标志并且 libc 不支持它,将会出现链接器错误)。

注意 users should not call __cxa_atexit directly: it takes arguments which only the compiler/linker is supposed to know (the __dso_handle).

… No user interface to __cxa_atexit is supported, so the user is not able to register an atexit function with a parameter or a home DSO.


MSVC 显然 does not use atexit()-like functions to run the global destructors. And according to MSVC 已经 运行 在 dlclose().

上的析构函数