Linux中等价于DllMain的函数名

32
在 *nix 中,是否有一个入口点在库被加载和卸载时被系统调用的 .so 库?
更实际的问题是:如果 .so 是用 C++ 编写的,并且其中包含具有构造函数和析构函数的全局对象,并且它从一个没有构造/析构概念的语言中加载,那么全局对象是否正确地构造/析构?
3个回答

24

您可以使用 __attribute__((constructor))__attribute__((destructor)) 在共享库加载和卸载时执行代码。


(注:此处已按要求翻译,保留了 HTML 标签,并使翻译更加通俗易懂。)

从GNU GCC手册中:"然而,目前为止,对于具有静态存储期限的C++对象的构造函数和带有属性构造函数的函数被调用的顺序是未指定的。" 然而,当静态存储对象已经初始化时,DllMain保证运行。如果您想在库的设置/拆卸函数中使用静态对象,则此保证非常重要。 - Alex Che
1
你可以在这里查看区别。 - Alex Che

21
  1. 没有与DllMain等价的函数。

  2. 对于JNI库,例如在Android上,可能会有一个特殊入口JNI_OnLoad,旨在填充JNI函数表。

  3. GCC定义了特殊属性constructor,允许在共享库加载时运行某些代码。

  4. C++保证全局和静态对象的构造函数将被执行,无论加载.so的代码是否意识到这些类或已经构造。

    同样适用于析构函数,但在某些不幸的情况下可能会有一些析构函数无法运行 - 例如发生sigfault且异常被禁用。


1
按照这个逻辑,每个构造函数都有点类似于 DllMain :) - Seva Alekseyev
3
不完全正确。DllMain对于每个已附加的线程都会运行——在Linux中没有类似的机制。而且,正如James Kanze在这里所回答的那样,全局对象构造函数是由运行时库而非通过DllMain机制运行的。 - Alex Cohn
但是,那么必须有一些操作系统级别的东西来调用RTL的全局初始化序列... - Seva Alekseyev
请参考http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html - 构造函数属性与C ++构造函数无关。 - Alex Cohn
2
@SevaAlekseyev:合同规定带有__attribute__((constructor))的函数将在dlopen()返回之前执行。 - Alex Cohn
显示剩余2条评论

6

所使用的技术略有不同,但全局对象的构造/销毁基本上内置于动态加载器中。(即使在Windows下,也无需通过DllMain。全局对象将正确地构造/销毁。)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接