C++ Linux共享库初始化&;同时使用c+时进行脱硝+;静态初始化器

C++ Linux共享库初始化&;同时使用c+时进行脱硝+;静态初始化器,c++,linux,gcc,initialization,shared-libraries,C++,Linux,Gcc,Initialization,Shared Libraries,我想自动调用来初始化和取消初始化我的共享库 在我的共享库中,我需要一些C++对象的静态初始化,其中包括使用第三方代码(例如UnTest++)。 当执行init函数时,需要保证所有C++链接对象(所有链接翻译单元)的静态初始化都完成(反之亦然);因此,与主程序()的执行条件相同的是C++程序中可以预期的。 我已经看到了很多关于linux共享库init/deinit的信息,例如: 但是提供的解决方案不适合我的需要。在这两种方法中(AyAtthiTyth>(构造函数)甚至是-WL,-init,

我想自动调用来初始化和取消初始化我的共享库

在我的共享库中,我需要一些C++对象的静态初始化,其中包括使用第三方代码(例如UnTest++)。 当执行init函数时,需要保证所有C++链接对象(所有链接翻译单元)的静态初始化都完成(反之亦然);因此,与主程序()的执行条件相同的是C++程序中可以预期的。 我已经看到了很多关于linux共享库init/deinit的信息,例如:
但是提供的解决方案不适合我的需要。在这两种方法中(AyAtthiTyth>(构造函数)甚至是-WL,-init,),在C++对象的静态初始化完全完成之前,调用init函数。 我还玩了
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu

class InitAndDeinit {
public:
    InitAndDeinit() {
        // Do some initialization
    }
    ~InitAndDeinit() {
        // Do some cleanup
    }
} initAndDeinit __attribute__((init_priority(65535)));
但这也不会将呼叫放在所需的位置;即使使用
\uuuu属性((构造函数(65535))

我已经用gcc 4.6.4、4.7.3和4.8.1进行了测试(4.6.4显示了与排序
\uuuuuu属性(构造函数))
略有不同的行为)

有什么建议吗


我目前的解决方法是提供导出函数(lib_init()和lib_deinit()),这些函数必须由应用程序手动调用。

这里有一个可能的解决方案

TU中的静态对象按其定义顺序初始化。将特殊类型的静态对象的定义
T
附加到每个源文件的末尾。
T
的构造函数应该递增一个静态零初始化成员。一旦计数器达到模块中的源文件数(由构建脚本确定),请调用
lib\u init()

lib_deinit()
在计数器减回到零后调用

每个库都应该有自己的
T


您应该能够修改makefile,这样您就不必实际更改源文件。例如,不要使用
g++-cfoo.c
而使用
g++-cmyspecialstaticinitcode.c-foo.c-包括foo.c
或类似的东西。

@Joe静态对象初始化和初始化顺序由处理.ctors和.dtors部分或.init_数组和fini_数组部分的加载程序或链接器确定。当加载器在返回前调用dlopen()时,将执行全局构造函数和静态对象初始化。这可能已经发生了,除非您正在使用的共享库是用“-nostartfiles”或“-nostdlib”编译的。运行时ABI规范没有提到它需要如何实现,它取决于链接器/加载程序。然而,该标准规定,在调用共享库的任何函数之前,必须进行静态数据和全局构造函数初始化

请看下面

5.2。库构造函数和析构函数 库应该使用gcc属性((构造函数))和属性((析构函数))函数属性导出初始化和清理例程。有关这些方面的信息,请参见gcc信息页面。构造函数例程在dlopen返回之前执行(如果在加载时加载库,则在启动main()之前执行)。析构函数例程在dlclose返回之前执行(如果库在加载时加载,则在exit()或main()完成之后执行)。这些功能的C原型是: void属性((构造函数))my_init(void); void属性((析构函数))my_fini(void)


不能使用gcc参数
-nostartfiles''或
-nostlib''编译共享库。如果使用了这些参数,则不会执行构造函数/析构函数例程(除非采取特殊措施)。

您是动态加载共享库还是链接到它们?“提供导出函数(
lib_init()
lib_deinit()
)”——从我所看到的,这是一个常见的习语。@Slava:它是动态链接的。在真正搜索和尝试了不同的方法后,我发现这个问题是大约一年前提出的,看起来我的问题是重复的。我在那里找到的唯一解决方案是试验链接器脚本(据我所知)。另一种方法是使用代理对象访问共享库:哇,这是一种多么棘手的方法。但它看起来也有点粗糙。我不想对我所有的翻译单位都有这样的影响。至少,由于使用了第三方代码,并不是所有的makefile都在我的控制之下。这种方法依赖于实际构造的特殊对象。据我所知,在调用TU中的任何函数之前,标准只要求这样做。它可能会在实践中起作用,但要证明它会起作用有点困难。@Kerrek这应该与gcc和gnu ld一起起作用,我并不是说它是可移植的。这不是因为标准中没有提到动态加载代码。@n.m:你能给我一个链接,看看标准中关于动态加载代码的规范吗?@Joe:标准中没有关于动态加载的内容。