在运行时,std 库何时完全初始化以便在不破坏代码的情况下使用它?

At runtime, when is the std library completely initialized for it to be used without breaking the code?

我正在开发一个项目,其中包含调用 main 之前的启动代码。但是我不知道 std 库初始化。

我知道下面的代码会抛出一个段错误。

#include <iostream>

void foo(void) __attribute__((constructor));
void foo() {
  std::cout << "foo" << std::endl;
}

int main() {
  std::cout << "Simple program to throw a segmentation fault" << std::endl;
}

可以通过使用 std::ios_base::Init mInitializer; 强制初始化 ostream 缓冲区(不确定它是否完全是 ostream)来使上面的代码工作。这意味着此时std库没有完全初始化(这是我对上面例子的推断)。

那么我什么时候可以在不破坏代码的情况下使用标准函数?有没有办法强制初始化完整的标准库?

documentation for the constructor attribute 是这样说的:

However, at present, the order in which constructors for C++ objects with static storage duration and functions decorated with attribute constructor are invoked is unspecified.

这意味着 ELF 构造函数和静态对象(用于 std::cout 初始化的对象)不能很好地混合。

另一方面,std::cout 是一个历史例外,因为它 依赖于 C++ 标准库中的构造函数。在 ELF 系统上,ELF 构造函数 运行 按拓扑顺序排列。这意味着动态链接器查看库依赖项(DT_NEEDED 条目)并在它们的依赖项初始化之前延迟库的初始化。

因此,C++ 代码可以假定 C++ 运行-time 库在构造 ELF 构造函数 运行 和应用程序定义的全局对象时已完全初始化。唯一的例外是 C++ 库,它抢占标准 C++ 标准库本身使用的例程(通过 ELF 符号插入),并且如果库之间存在循环依赖性,则没有正确的初始化顺序。这两种情况都不常见,除非您编写自定义 malloc 或类似的东西,否则可以通过适当的应用程序设计来避免。