【问题标题】:How to make sure a global constructor is called after all static object initializations (DllMain equivalent)?如何确保在所有静态对象初始化后调用全局构造函数(等效于 DllMain)?
【发布时间】:2013-07-28 21:23:39
【问题描述】:

我正在尝试制作一个 C++ 库,我需要在加载时调用一个函数来对其进行初始化。我使用的是GCC,所以我尝试使用__attribute__((constructor)),该函数实际上是在加载时调用的。

但上述函数使用了不同翻译单元中的静态对象,因此未指定这些翻译单元中的静态对象是否在我需要使用它们时进行初始化。所以,举个例子,如果我想在这个函数中使用 std::cout,我就完蛋了。

下面的代码 sn-p 很好地说明了这个问题:

#include <iostream>

void __attribute__((constructor)) init()
{
    std::cout << "Test\n";
}

int main(int argc, char* argv[])
{
    return 0;
}

这里,函数init()会在加载时被调用,但未指定此时std::cout是否被初始化,并且在尝试执行第5行时很可能会出错。

所以我的问题是,是否有可能确保我需要在加载时调用的初始化函数将在所有静态对象构建后执行?

编辑:我忘了提到这个库将通过使用 LD_PRELOAD 环境变量在另一个程序中预加载来使用,以便拦截某些调用,所以我不能要求用户在他的 main 中调用 lib_init() 函数()。

【问题讨论】:

  • 除非你把它放在dllmainmain 中。
  • 问题是,我正在做一个库,所以我不能使用main,我使用的是GCC,所以我也不能使用dllmain。我不想相信这会是 MSVC 特有的功能。
  • @Loki Astari:我认为这不会解决问题:不同翻译单元中的对象仍然可能未初始化。
  • 如果您能提供帮助,请不要接触特定于编译器的内容。使用正确的单例对象,以保证它们的初始化以正确的顺序发生。
  • std::cout 很特别,我相信有一些保证。并且访问其他翻译单元中的对象,您应该使用函数静态成员变量来保证初始化的顺序。但这不是你的问题。您需要将更多细节放入您需要什么的问题中。

标签: c++ linux gcc


【解决方案1】:

如果这将是一个供第 3 方使用的库,我强烈坚持要求手动调用此类“init”函数作为使用合同的一部分。否则,您的用户可能会发现他们处于非常不愉快的境地,他们被您的 lib 的直线行为所束缚。

作为证据,有一个 WinSock 示例:在调用 WSAStartup() 之前,假定没有任何工作。

【讨论】:

  • 我忘了说这个库会被注入到其他带有 LD_PRELOAD 的程序中,所以很遗憾我不能要求用户在他的主函数中调用初始化函数。
猜你喜欢
  • 2011-05-28
  • 1970-01-01
  • 1970-01-01
  • 2010-11-14
  • 1970-01-01
  • 2011-02-15
  • 1970-01-01
  • 1970-01-01
  • 2011-02-26
相关资源
最近更新 更多