如何在共享库中调用 atexit?

how to call atexit in a shared library?

在共享库中,函数 func1() 有 atexit(terminate_global) 而这个共享库没有'attribute ((constructor))'和'属性((析构函数))'。
所以,程序流程如下:
1) 应用程序使用 dlopen 加载共享库。
2) 应用程序使用 dlsym 调用 func1()。
3) func1() 有 atexit(terminate_global)。
4) func1() returns。
5) 应用程序调用 dlclose 以取消分配库。

在上述步骤中,我没有发现卸载库时调用了 atexit()。那么,如果在我们取消分配共享库时必须调用 atexit() ,那么正确的方法应该是什么?我是否应该使用 attribute((constructor)) 和 attribute((destructor)) 函数属性导出例程,以便可以调用 atexit 注册函数?

我假设传递给 atexitterminate_global 函数是在插件中定义的。如果 terminate_global 是由 主程序 定义的 global 函数(与 -rdynamic 标志链接,以获取其符号访问到插件)然后一个插件可以调用 atexit(terminate_global),但是我会提供一些 API 函数来做那个。

我不会那样做(调用 atexit(terminate_fun) inside 一些插件,其中 terminate_fun 是插件定义的函数),除非你确定您的应用程序从不 dlclose-ing 插件。

如果您的应用程序在某处调用 dlclose - 在某些 atexit-ing 函数之外 - 那 dlclose 可能 munmap plugin.so 和当稍后 exit 正在处理 atexit 时,它将崩溃(因为指向通过 atexit 注册的函数的指针无效且未映射)

您必须定义谁负责 dlclose-ing 插件。如果您的应用程序明确地这样做,您可以通过 __attribute__((destructor)) C 函数(或插件中某些静态 C++ 数据的析构函数)完成一些清理工作,或者 定义并记录约定 告诉例如每个插件都有一个名为 plugin_cleanup 的函数(你会用 dlsym 得到)将适当地调用该清理函数。

您可以通过其他方式定义和记录插件不是 明确 dlclose-d 的应用程序(这通常没问题,特别是如果您提供一些清理机制).但是,这可能会让 valgrind 不高兴。