【问题标题】:Using cout in the constructor of a class that is included in another class as a static member在作为静态成员包含在另一个类中的类的构造函数中使用 cout
【发布时间】:2020-07-05 07:32:02
【问题描述】:

以下代码

#include <iostream>

struct A {
    A() {
        std::cout << std::endl;
    }
};

struct B {
    static inline A a;
};

int main() {
}

使用 gcc 编译成功,但使用 clang 编译后因分段错误而崩溃。是代码不标准还是clang错误?

https://godbolt.org/z/tEvfrW

【问题讨论】:

  • MVCC 的结果与GCC 的结果相同。 clang 处理 static inline A a; 的方式有些奇怪?另外,我认为copy-elision 将在其中发挥作用(虽然我可能错了......)
  • @molbdnilo,我猜我们有stronger guarantee标题&lt;iostream&gt; 的行为就好像它(直接或间接)定义了一个具有静态存储持续时间的std::ios_base::Init 实例:这使得使用有序初始化访问静态对象的构造函数和析构函数中的标准 I/O 流是安全的(只要在定义这些对象之前将#include &lt;iostream&gt; 包含在翻译单元中)。 如果我们将@987654332 @ 不是 inline,它有效。
  • 内联对象是什么意思?
  • @d4rk4ng31 c++17 功能
  • 哪个版本的 Clang 会崩溃?它适用于Apple clang version 11.0.0

标签: c++ clang language-lawyer initialization-order


【解决方案1】:

std::ios_base::Initreads 上的 Cppreference:

标头&lt;iostream&gt; 的行为就像它定义(直接或间接)具有静态存储持续时间的std::ios_base::Init 实例:这使得在静态对象的构造函数和析构函数中访问标准I/O 流变得安全有序初始化(只要在定义这些对象之前,#include &lt;iostream&gt; 包含在翻译单元中)。

你确实在B::a之前包含了&lt;iostream&gt;,但是B::a的初始化(B::astatic inline变量)不是ordered initialization的一部分,所以它可以在std::ios_base::Init之前初始化。似乎 Clang(至少某些版本)正是这样做的。这是一种有效的行为。

标准为 ([basic.start.dynamic]):

  1. 如果变量是隐式或显式实例化的特化,则具有静态存储持续时间的非局部变量的动态初始化是无序的,如果变量是不是隐式或显式实例化的特化的内联变量,则它是部分排序的,并且否则订购。

因此,std::ios_base::Init 实例的初始化是有序的,B::a 的初始化是部分有序的。

  1. 具有静态存储时长的非局部变量VW的动态初始化顺序如下:

3.1。如果VW 有有序初始化并且V 的定义在W 的定义之前是按外观有序的,或者如果V 有部分有序初始化,W 没有无序初始化,并且对于W 的每个定义E 存在V 的定义D 使得DE 之前按外观排序,然后...

3.2。否则,如果程序在VW初始化之前启动了主线程以外的线程,则未指定VW的初始化发生在哪个线程;如果它们发生在同一个线程中,则初始化是无序的。

3.3。否则VW的初始化是不确定的。

3.1 和 3.2 不适用。所以我们有不确定的初始化序列。

您可以在使用std::coutfor example 之前将B::a 设为非inline 静态变量或以某种方式强制std::ios_base::Init 初始化:

struct A {
    A() {
        std::cout << std::endl;
    }

    std::ios_base::Init init;
};

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-07-13
    • 1970-01-01
    • 2016-07-28
    • 1970-01-01
    • 1970-01-01
    • 2017-03-17
    • 2013-06-18
    相关资源
    最近更新 更多