以下代码
#include <iostream>
struct A {
A() {
std::cout << std::endl;
}
};
struct B {
static inline A a;
};
int main() {
}
使用 gcc 编译后成功,但使用 clang 编译后因分段错误而崩溃。代码不标准还是clang错误?
以下代码
#include <iostream>
struct A {
A() {
std::cout << std::endl;
}
};
struct B {
static inline A a;
};
int main() {
}
使用 gcc 编译后成功,但使用 clang 编译后因分段错误而崩溃。代码不标准还是clang错误?
Cppreferencestd::ios_base::Init
读取:
标头的
<iostream>
行为就好像它(直接或间接)定义了一个具有静态存储持续时间的实例:这使得在具有有序初始化std::ios_base::Init
的静态对象的构造函数和析构函数中访问标准 I/O 流变得安全(只要包含在定义这些对象之前的翻译单元)。#include <iostream>
您确实包含<iostream>
before B::a
,但B::a
(可变)的初始化不是有序初始化的一部分B::a
,因此可以在 before 初始化。似乎 Clang(至少某些版本)正是这样做的。这是一个有效的行为。static inline
std::ios_base::Init
标准内容为([basic.start.dynamic]):
- 如果变量是隐式或显式实例化的特化,则具有静态存储持续时间的非局部变量的动态初始化是无序的,如果变量是不是隐式或显式实例化的特化的内联变量,则它是部分排序的,否则是有序的.
因此,实例的初始化std::ios_base::Init
是有序的,而 的初始化B::a
是部分有序的。
- 非局部变量的动态初始化
V
和W
静态存储持续时间的顺序如下:3.1。如果
V
和W
有有序的初始化并且 的定义V
在 的定义之前是有序的W
,或者如果V
有部分有序的初始化,W
没有无序的初始化,并且对于 的每个定义E
都W
存在这样的定义D
,它在 的定义之前是有序的,然后 ...V
D
E
3.2.
V
否则,如果程序在初始化或初始化之前启动了主线程以外的线程W
,则未指定初始化V
和W
发生的线程;如果它们发生在同一个线程中,则初始化是无序的。3.3.
V
否则,和的初始化W
是不确定的。
3.1 和 3.2 不适用。所以我们有不确定顺序的初始化。
您可以在使用之前创建B::a
一个非inline
静态变量或以某种方式强制std::ios_base::Init
初始化std::cout
,例如:
struct A {
A() {
std::cout << std::endl;
}
std::ios_base::Init init;
};