我试图弄清楚全局对象的构造函数是如何调用的。 我知道在使用翻译单元中的任何内容之前都会调用它们,我对此很好。 我试图找出在Linux和Windows(x86和x64)中如何做到这一点。
我似乎记得Windows(x86)使用链表进行构建和破坏,但是我很难找到有关此问题的任何资源。
我找到了以下有关相关主题的材料,但似乎没有什么能准确涵盖我正在寻找的内容。
http://blogs.msdn.com/b/freik/archive/2005/03/17/398200.aspx
http://msdn.microsoft.com/en-us/library/9b372w95.aspx
http://msdn.microsoft.com/en-us/library/7kcdt6fy.aspx
和 PE 文件格式文档。
谁能指出我找到这些信息的正确方向?
以防万一你不明白,我这里有代码来演示。来源A.cpp
#include "stdafx.h"
extern bool DoFunctionB();
class MyClassA {
protected:
bool bIsInitialized;
bool bIsBInitialized;
public:
MyClassA () : bIsInitialized(true) {
bIsBInitialized = DoFunctionB();
}
bool IsInitialized() {
return bIsInitialized;
}
};
static MyClassA MyClassGlobal;
bool DoFunctionA() {
return MyClassGlobal.IsInitialized();
}
来源B.cpp
#include "stdafx.h"
extern bool DoFunctionA();
class MyClassB {
protected:
bool bIsInitialized;
bool bIsAInitialized;
public:
MyClassB () : bIsInitialized(true) {
bIsAInitialized = DoFunctionA();
}
bool IsInitialized() {
return bIsInitialized;
}
};
static MyClassB MyClassGlobal;
bool DoFunctionB() {
return MyClassGlobal.IsInitialized();
}
主.cpp
#include "stdafx.h"
extern bool DoFunctionA();
extern bool DoFunctionB();
int _tmain(int argc, _TCHAR* argv[])
{
bool a = DoFunctionA();
bool b = DoFunctionB();
return 0;
}
将这些内容添加到新的 Windows 控制台应用。 将断点放在构造函数和 DoFunctionX() 代码中。 按 F11 并逐步完成它。 您将看到,无论哪个全局初始值设定项首先被调用,都将在初始化该文件中的静态对象之前使用另一个 cpp 文件中的 DoFunction。
不管你认为标准是什么。 这就是编译器所做的。 这是你必须关注的危险。
如果您在构造函数中将堆栈提升 2 个步骤,您将看到我已经告诉您的指针列表。
快乐编码。
认为在使用对象之前必须运行全局构造函数是错误的。 我已经基于这个假设修复了许多错误,但它根本不是真的。 不适用于 gcc,也不适用于 MSVC,当然不适用于 XCode。
您可以在 gcc 中指定一个属性((init_priority(X))) 来强制排序,
或 #pragma init_seg({ 编译器 | 库 | 用户 |"section-name" [, func-name]} ) for msvc.
使用 XCode 时,初始化代码将按照对象文件传递到链接器的顺序运行。
我不认为有标准,如果有的话,很少有人遵循它。 由工具创建者决定如何跟踪初始化的内容和时间。