在运行时,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
或类似的东西,否则可以通过适当的应用程序设计来避免。
我正在开发一个项目,其中包含调用 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
或类似的东西,否则可以通过适当的应用程序设计来避免。