内置对象/库的静态初始化顺序失败

时间:2016-04-12 03:40:33

标签: c++

如果我有一些静态初始化的变量(main开始之前),我可以自由使用这些构造函数中的任何内置函数,例如<iostream><vector>

出现“静态初始化顺序失败”是因为静态变量初始化的顺序(在不同的转换单元中)是未定义的。

那么如果像

那样良性的话会怎么样?

std::cout << "Hello" << std::endl;

碰巧依赖于<iostream>内的一些静态变量提前初始化? (我不是说它确实如此,但假设它确实如此。)什么说内置库中的这些静态变量是在我自己的静态变量之前初始化的?比如里面说"Person.cpp"或其他什么。

修改: Is std::cout guaranteed to be initialized?被建议与此问题重复。但是,我认为我的问题范围略宽,因为它询问任何标准内置库,而不仅仅是<iostream>

2 个答案:

答案 0 :(得分:1)

C++标准在main开始之前或main完成之后没有强烈声明程序的行为。

根据经验,我发现了一些问题,其中C ++运行时已经破坏了一些对象(例如用于管理std :: mutex的资源),这些问题在破坏复杂类型时造成了死锁。

我建议使用以下静态模式

C ++按照执行顺序在函数中创建声明为static的对象。这留下了一个模式,可以确保在需要时存在对象。

   AnObject * AnObject::getInstance() {
       static AnObject a;
       return &a;
   }

这应该被执行以获取全局,并且将在调用getInstance()时发生。

C ++ 11以后

此代码保证是线程安全的,如果多个执行线程到达getInstance,则只有一个将构造对象,其余的将等待。

Pre C ++ 11

创建此模式会将错误定义的顺序替换为线程安全问题。

幸运的是,可以在main中创建一个criticalsection / mutex primative,它可以进行仲裁。

在某些操作系统(例如InitializeCriticalSection和Windows)中,可以在main之前安全地创建这些锁,作为静态变量。

   AnObject * AnObject::getInstance() {
       EnterCriticalSection( &aObjectcrit );
       static AnObject a;
       LeaveCriticalSection( &aObjectcrit );
       return &a;
   }

假设您在调用此函数之前或之前初始化了aObjectcrit。

这种模式的结果是洋葱构造的一种形式,其中对象按需要的顺序是必需的,当程序退出时,它们将按照它们创建的相反顺序销毁。

答案 1 :(得分:0)

您会混淆对象(std::cout)和类型(std::vector)。前者由关联问题覆盖,后者是一种类型。静态初始化适用于对象,但不适用于类型。