1

在共享库中,函数 func1() 具有 atexit(terminate_global) 并且此共享库没有“属性((constructor))”和“属性((destructor))”。
因此,程序流程如下:
1) 应用程序使用 dlopen 加载共享库。
2) 应用程序使用 dlsym 调用 func1()。
3) func1() 有 atexit(terminate_global)。
4) func1() 返回。
5) 应用程序调用 dlclose 取消分配库。

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

4

1 回答 1

0

我假设terminate_global传递给的函数atexit是在插件中定义的。如果terminate_global是由主程序定义的全局函数(与标志链接,以使其符号访问插件),则插件可以调用,但我会提供一些 API 函数来执行此操作。-rdynamicatexit(terminate_global)

我不会那样做(在某个插件atexit(terminate_fun) 内部terminate_fun调用插件 定义的函数),除非您确定您的应用程序永远不会 dlclose使用插件。

如果您的应用程序在某个地方调用dlclose- 在某些atexit-ing 函数之外 - 这dlclose很可能会munmapplugin.so稍后exit处理atexit时崩溃(因为指向通过注册的函数的指针atexit无效且未映射)

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

否则,您可以定义和记录插件不是由您的应用程序显式 dlclose-d 的(这通常是可以的,特别是如果您提供一些清理机制)。但是,这可能会让人valgrind不高兴。

于 2015-03-30T12:06:57.727 回答