Mar*_*ork 69
正如您所说,订单在不同的编译单元中是未定义的.
在同一个编译单元中,订单定义明确:与定义相同的顺序.
这是因为这不是在语言级别解决,而是在链接器级别解决.所以你真的需要查看链接器文档.虽然我真的怀疑这将有助于任何有用的方式.
对于gcc:查看ld
我发现即使更改链接的对象文件的顺序也可以更改初始化顺序.因此,您需要担心的不仅仅是链接器,而是构建系统如何调用链接器.即使尝试解决问题实际上也是一个不起眼的问题.
这通常只是在初始化全局时在初始化期间相互引用的问题(因此仅影响具有构造函数的对象).
有解决问题的技巧.
小智 18
我希望模块之间的构造函数顺序主要取决于将对象传递给链接器的顺序.
然而,GCC不会让你使用init_priority显式指定的顺序全球构造函数:
class Thingy
{
public:
Thingy(char*p) {printf(p);}
};
Thingy a("A");
Thingy b("B");
Thingy c("C");
Run Code Online (Sandbox Code Playgroud)
按照你的预期输出"ABC",但是
Thingy a __attribute__((init_priority(300))) ("A");
Thingy b __attribute__((init_priority(200))) ("B");
Thingy c __attribute__((init_priority(400))) ("C");
Run Code Online (Sandbox Code Playgroud)
输出'BAC'.
Nic*_*ith 13
既然你已经知道除非绝对必要,否则你不应该依赖这些信息.我对各种工具链(MSVC,gcc/ld,clang/llvm等)的一般观察是,目标文件传递给链接器的顺序是它们的初始化顺序.
这有例外,我没有声称所有这些,但这里是我遇到的那些:
1)4.7之前的GCC版本实际上以链接线的相反顺序初始化.GCC中的这张票是发生变化的时候,它打破了许多依赖于初始化顺序的程序(包括我的!).
2)在GCC和Clang中,构造函数优先级的使用可以改变初始化顺序.请注意,这仅适用于声明为"构造函数"的函数(即它们应该像全局对象构造函数一样运行).我已经尝试使用这样的优先级,并发现即使在构造函数上具有最高优先级,所有没有优先级的构造函数(例如,普通的全局对象,没有优先级的构造函数)都将首先被初始化.换句话说,优先权仅相对于具有优先权的其他职能,但真正的头等公民是没有优先权的人.更糟糕的是,由于上述第(1)点,此规则实际上与4.7之前的GCC相反.
3)在Windows上,有一个非常简洁有用的共享库(DLL)入口点函数,称为DllMain(),如果已定义,将在所有全局数据初始化后直接使用等于DLL_PROCESS_ATTACH的参数"fdwReason"运行.在消费应用程序有机会调用DLL上的任何函数之前.这在某些情况下非常有用,并且在使用GCC或Clang with C或C++的其他平台上绝对没有类似的行为.你会发现最接近的是构造函数具有优先级(参见上面的第(2)点),这绝对不是同一个东西,并且不适用于DllMain()适用的许多用例.
4)如果您使用CMake生成构建系统(我经常这样做),我发现输入源文件的顺序将是它们生成给链接器的结果对象文件的顺序.但是,您的应用程序/ DLL通常也会链接到其他库中,在这种情况下,这些库将在输入源文件之后位于链接行上.如果您希望将一个全局对象作为第一个初始化对象,那么您很幸运,您可以将包含该对象的源文件放在源文件列表中的第一个.但是,如果您希望有一个是最后一个进行初始化(可以有效地复制DllMain()行为!)那么您可以使用该源文件调用add_library()以生成静态库,并添加生成的静态库作为target_link_libraries()调用应用程序/ DLL的最后一个链接依赖项.在这种情况下,请注意您的全局对象可能会得到优化,并且您可以使用--whole-archive标志强制链接器不要删除该特定小型归档文件的未使用符号.
关闭提示
要完全了解链接的应用程序/共享库的初始化顺序,请将--print-map传递给ld链接器,将grep传递给.init_array(或者在4.7之前的GCC中,将grep传递给.ctors).每个全局构造函数将按其初始化的顺序打印,并记住在4.7之前的GCC中的顺序相反(参见上面的第(1)点).
写这个答案的动机因素是我需要知道这些信息,除了依赖初始化顺序之外别无选择,并且在其他SO帖子和互联网论坛中只发现了这些信息的稀疏位.其中大部分是通过大量实验学到的,我希望这可以节省一些人的时间!
| 归档时间: |
|
| 查看次数: |
66681 次 |
| 最近记录: |