【问题标题】:Visual C++: Is global variables initialization order deterministic during DLL loading?Visual C++:在 DLL 加载期间全局变量初始化顺序是否确定?
【发布时间】:2020-03-28 16:04:01
【问题描述】:

假设我构建了一个简单的 DLL,由两个翻译单元组成:

第一

// foo.cpp
struct Foo
{
  //...
} g_foo;
// ... other stuff

第二个

// bar.cpp
struct Bar
{
  //...
} g_bar;
// ... other stuff

我知道 C++ 标准没有指定全局变量初始化的顺序。问题是:一旦我构建了 Windows DLL,在LoadLibrary 调用期间执行的全局变量初始化的顺序是确定性的(每个LoadLibrary 调用都会以相同的顺序启动变量g_foog_bar 的初始化)或者它可能取决于一些加载器/系统设置?

【问题讨论】:

  • DllMain 的文档和链接的一般最佳实践中所述,您可以在其中执行的操作:只有Kernel32.dll 可以假定为已加载,在DllMain 内部。因此:库的实际加载顺序是不确定的。
  • 无论使用多少个翻译单元来创建它,一个 DLL 只能有一个 DllMain 函数,这就是 Windows 为初始化 DLL 而调用的函数。从那时起,DLL 中初始化选项的顺序由 DLL 本身的代码决定。所以是的,如果你的 DLL 没有改变,初始化的顺序应该是一致的。但我当然同意你需要非常小心你在 DllMain 时所做的事情,其中​​包括静态变量初始化器。
  • @AlgirdasPreidžius 我的意思是同一个库中全局变量的初始化顺序。将此添加到问题描述中。
  • @undermind 我不知道这是否能解决您的直接问题,但我记得前一段时间搜索过,关于何时在 DLL 中初始化全局对象:devblogs.microsoft.com/oldnewthing/20141017-00/?p=43823;这更通用,当全局变量被初始化时,关于 C++ 标准:stackoverflow.com/questions/54159044/…(有多个类似的问题)。

标签: c++ visual-c++ dll global-variables initialization-order


【解决方案1】:

我知道 C++ 标准没有指定顺序 全局变量初始化。 准确地说,当全局变量位于单个翻译单元中时,它会这样做:

Ordered dynamic initialization, which applies to all other non-local variables: within a single translation unit, initialization of these variables is always sequenced in exact order their definitions appear in the source code.

您在上面的 DLL 代码中,在两个不同的翻译单元中有两个不同的全局变量,将在链接之前生成两个不同的 .OBJ 文件。然后,当 .OBJ 文件链接在一起形成 .DLL 时,C++“pre-main”运行时代码将附加到 .DLL。当 .DLL 通过 process-launch 或 LoadLibrary 绑定到进程的地址空间时,此存根代码将有权访问 DLL 中的表,在调用 DllMain 之前,它将遍历,调用表中链接时间合成的静态非成员函数,每个非成员函数的任务是在表中为相应的全局对象运行类成员构造函数。自然,在从进程地址空间中删除 DLL 期间,通过进程退出或FreeLibrary,非成员函数将被类似地调用,但以相反 (LIFO) 的顺序。

鉴于此表是由 LINK.EXE “烘焙”到 .DLL 中的,因此 DLL 中全局变量的构造顺序,无论它们来自相同的翻译单元还是不同的翻译单元,都将是预先确定的。正如您所指出的,在链接时间之前它不会是可预测的,但无论它在链接时间之后变成 什么,它都会在 .DLL 的生命周期内保持不变因为只有 LINK.EXE 有能力构造那个全局变量构造函数表,一旦构造了就构造了。

如果有人想知道哪个先出现:全局变量的构造,还是程序员提供的 DllMain,那就是前者。 C++ 运行时代码调用程序员提供的 DllMain,如 link provided by @Algirdas Preidžius 所示。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-20
    • 1970-01-01
    相关资源
    最近更新 更多