这里的答案表明 __attribute__((constructor)) 不是在静态初始化之后调用的,而是按声明顺序调用的。
那么,如果不保证在所有数据初始化时调用它,它的目的是什么?我们也可以在 Foo 构造函数中包含我们的 ((constructor)) 代码。
我正在寻找的是一种在共享库中拥有在初始化所有静态数据并调用静态构造函数后将执行的代码的方法。我看到人们推荐 __attribute__((constructor)) 作为 DllMain 的替代品;我们可以看到这是错误的,因为一些静态数据可能还没有初始化。
当然,在单个文件(编译单元)中,我们可以安排静态。但是在一个典型的程序中有很多文件。有没有办法保证一个文件中的 ((constructor)) 在共享库中的所有其他静态变量都被初始化后肯定会被调用?
如果我将带有静态初始化(构造函数、对象等)的文件放在 gcc 命令行的末尾:
g++ -shared -fPIC source1.o source2.o MyLastInitChance.o
这个文件的静态构造函数是否保证最后被调用?我进行了实验,当我更改源文件的顺序时,printfs 的顺序发生了变化;但它是否在某处指定并保证在编译系统/计算机中相同?
例如,引用:
在链接时,gcc 驱动程序将 crtbegin.o 放在所有可重定位文件之前,并将 crtend.o 放在所有可重定位文件之后。©
据我了解,上面的引用暗示传递给链接器的 .o 文件的顺序定义了静态初始化的顺序。我对么?
另一个有趣的可能解决方案可能是编写一个 GCC 插件来调整静态初始化(例如,将代码添加到 .ctors 部分等)。但这只是一个想法,也许有人可以扩展。
这里介绍了另一种可能的解决方案。简而言之,可以使用外部构建后工具对可执行文件(库)中的 .ctors 条目进行重新排序。但我不是 ELF 格式的专家;我想知道以这种方式调整 .so 文件是否可行且足够容易。
我感兴趣的是解决一个特定的问题,或者证明它是不可能解决的(至少为什么上面的解决方案不起作用)。