以下代码
#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 inlinestd::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,它在 的定义之前是有序的,然后 ...VDE3.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;
};