我正在开发一个项目,其中包含调用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库尚未完全初始化(这是我对上述示例的推断)。
那么什么时候才能使用std函数而不会破坏代码呢?有没有办法强制初始化完整的std库?
答案 0 :(得分:2)
documentation for the constructor
attribute说:
但是,目前,调用具有静态存储持续时间的C ++对象的构造函数和用属性
constructor
修饰的函数的顺序是未指定的。
这意味着ELF构造函数和静态对象(用于初始化std::cout
)不能很好地混合。
另一方面,std::cout
是一个历史异常,因为它不依赖于C ++标准库中的构造函数。在ELF系统上,ELF构造函数以拓扑顺序运行。这意味着动态链接器会查看库依赖项(DT_NEEDED
条目),并在初始化它们的依赖项之前延迟库的初始化。
因此,当ELF构造函数运行并构造应用程序定义的全局对象时,C ++代码可以假定C ++运行时库已完全初始化。唯一的例外是C ++库,它抢占了标准C ++标准库本身使用的例程(通过ELF符号插入),并且如果库之间存在循环依赖关系,那么就没有正确的初始化顺序。这两种情况都不常见,除非您编写自定义malloc
或类似内容,否则可以通过适当的应用程序设计来避免。