我希望自动调用初始化和取消初始化我的共享库。
在我的共享库中,我需要对C ++对象进行一些静态初始化,其中包括使用第三方代码(例如UnitTest ++)。 当执行我的init函数时,我需要保证,C ++对象(所有链接的翻译单元)的所有静态初始化都已完成(反之亦然);因此,与main()的执行在C ++程序中所期望的条件相同。
我已经看到很多关于linux共享库init / deinit的信息,例如像:
__attribute__((constructor))
和偶数-Wl,-init,<function name>
)中,似乎在完全完成C ++对象的静态初始化之前调用了init函数。
我还和__attribute__ ((init_priority(…)))
一起玩过:
class InitAndDeinit {
public:
InitAndDeinit() {
// Do some initialization
}
~InitAndDeinit() {
// Do some cleanup
}
} initAndDeinit __attribute__((init_priority(65535)));
但是,这也不会将呼叫置于所需的位置;即使是__attribute__((constructor(65535)))
。
我用gcc 4.6.4,4.7.3和4.8.1进行了测试(4.6.4显示了对__attribute__((constructor))
的排序略有不同的行为。
有什么建议吗?
我目前的解决方法是提供必须由应用程序手动调用的导出函数(lib_init()和lib_deinit())。
答案 0 :(得分:1)
这是一种可能的解决方案。
TU中的静态对象按其定义顺序初始化。将特殊类型T
的静态对象的定义附加到每个源文件的末尾。 T
的构造函数应该增加静态零初始化成员。一旦计数器达到模块中的源文件数(由构建脚本确定),请调用lib_init()
。
lib_deinit()
。
每个库都应该有自己的T
。
您应该能够修改您的makefile,这样您就不必在物理上改变源文件。例如,而不是g++ -c foo.C
使用g++ -c myspecialstaticinitcode.C -o foo.C -include foo.C
或类似的东西。
答案 1 :(得分:0)
@Joe静态对象的初始化和初始化的顺序由处理.ctors和.dtors节或.init_array和fini_array节的加载程序或链接程序确定。当加载程序在返回之前调用dlopen()时,将进行全局构造函数和静态对象初始化。除非使用的共享库是通过-nostartfiles或-nostdlib编译的,否则它可能已经发生了。运行时ABI规范没有提到它是如何实现的,它取决于链接器/加载器。但是,该标准指出,必须先进行静态数据和全局构造函数初始化,然后才能调用共享库的任何功能。
请参见下文。
5.2。库构造函数和析构函数 库应使用gcc attribute ((constructor))和 attribute ((destructor))函数属性导出初始化和清理例程。有关这些信息,请参见gcc信息页面。构造函数例程在dlopen返回之前执行(如果在加载时加载了库,则在main()启动之前)将被执行。析构函数例程在dlclose返回之前执行(如果在加载时加载了库,则在exit()或main()完成之后)执行。这些功能的C原型是: void 属性((构造函数))my_init(void); void 属性((析构函数))my_fini(void);
不得使用gcc参数-nostartfiles'' or
-nostdlib编译共享库。”如果使用这些参数,则将不执行构造函数/析构函数例程(除非采取特殊措施)。