答案here https://stackoverflow.com/questions/8433484/c-static-initialization-vs-attribute-constructor表明 __attribute__((constructor)) 未被调用after静态初始化,按声明顺序调用。
那么,如果不能保证所有数据初始化时都会调用它,那么它的目的是什么呢?我们也可以将 ((constructor)) 代码放在 Foo 构造函数中。
我正在寻找一种方法,在共享库中拥有将在初始化所有静态数据并调用静态构造函数后执行的代码。我看到人们推荐 __attribute__((constructor)) 作为 DllMain 的替代品;我们可以看到这是错误的,因为一些静态数据可能仍未初始化。
当然,在单个文件(编译单元)中我们可以安排静态数据。但在典型的程序中会有很多文件。有没有一种方法可以保证在共享库中的所有其他静态变量初始化后,一个文件中的 ((constructor)) 一定会被调用?
如果我将带有静态初始化(构造函数、对象等)的文件放在 gcc 命令行的末尾:
g++ -shared -fPIC source1.o source2.o MyLastInitChance.o
该文件的静态构造函数是否保证最后被调用?我进行了实验,当我更改源文件的顺序时,printfs 的顺序也会更改;但它是否在某处指定并保证在编译系统/计算机之间相同?
例如引用一段话:
在链接时,gcc 驱动程序将 crtbegin.o 紧接在所有内容之前
可重定位文件和 crtend.o 在所有之后立即
可重定位文件。© http://l4u-00.jinr.ru/usoft/WWW/www_debian.org/Documentation/elf/node4.html
根据我的理解,上面的引用意味着传递给链接器的 .o 文件的顺序定义了静态初始化的顺序。我对么?
另一个有趣的可能解决方案可能是编写一个调整静态初始化的 GCC 插件(例如,将代码添加到 .ctors 部分等)。但这只是一个想法,也许有人可以扩展。
另一种可能的解决方案是呈现 https://bugzilla.mozilla.org/show_bug.cgi?id=606137这里。简而言之,可以使用外部构建后工具对可执行文件(库)中的 .ctors 条目重新排序。但我不是 ELF 格式的专家;我想知道这是否可能并且足够容易以这种方式调整 .so 文件。
我感兴趣的是解决一个特定的问题,或者证明它是不可能解决的(至少为什么上面的解决方案不起作用)。