如果在全局对象的析构函数中调用 std::exit 会发生什么?
What should happen if one calls `std::exit` in a global object's destructor?
考虑以下代码:
#include <cstdlib>
struct Foo {
~Foo() {
std::exit(0);
}
} foo;
int main() {
}
它在我的Linux(GCC,Clang)和Windows(Visual Studio)上成功编译并以零终止。然而,当用MSYS2的GCC在Windows(g++ (Rev2, Built by MSYS2 project) 10.3.0
)上编译时,它进入无限递归并死于堆栈溢出。这可以通过在 std::exit()
之前添加一些调试输出来检查;我一开始没有加上,以免想到std::cout
.
的破坏
是否有任何 C++ 标准对这种行为有任何规定?是 well-defined/implementation-defined/undefined/etc 吗?
例如,最近的一些草稿 [support.start.term]/9.1
对 std::exit
的行为进行了如下描述:
First, objects with thread storage duration and associated with the current thread are destroyed.
Next, objects with static storage duration are destroyed and functions registered by calling atexit are called. See [basic.start.term] for the order of destructions and calls.
指的是[basic.start.term]/1
,我猜:
Constructed objects ([dcl.init]) with static storage duration are destroyed and functions registered with std::atexit are called as part of a call to std::exit ([support.start.term]).
The call to std::exit is sequenced before the destructions and the registered functions.
我没有看到在析构函数中调用 std::exit
有任何直接限制。
旁注:请不要评论“这段代码不好”、“thou shalt not use destructors in global objects”(您可能不应该这样做)以及在评论中探讨 XY 问题。考虑这是一个好奇的学生提出的学术问题,他知道对他们的原始问题有更好的解决方案,但在探索 C++ 的广阔草地时偶然发现了这个怪癖。
If std::exit
is called to end a program during the destruction of an object with static or thread storage duration, the program has undefined behavior.
考虑以下代码:
#include <cstdlib>
struct Foo {
~Foo() {
std::exit(0);
}
} foo;
int main() {
}
它在我的Linux(GCC,Clang)和Windows(Visual Studio)上成功编译并以零终止。然而,当用MSYS2的GCC在Windows(g++ (Rev2, Built by MSYS2 project) 10.3.0
)上编译时,它进入无限递归并死于堆栈溢出。这可以通过在 std::exit()
之前添加一些调试输出来检查;我一开始没有加上,以免想到std::cout
.
是否有任何 C++ 标准对这种行为有任何规定?是 well-defined/implementation-defined/undefined/etc 吗?
例如,最近的一些草稿 [support.start.term]/9.1
对 std::exit
的行为进行了如下描述:
First, objects with thread storage duration and associated with the current thread are destroyed. Next, objects with static storage duration are destroyed and functions registered by calling atexit are called. See [basic.start.term] for the order of destructions and calls.
指的是[basic.start.term]/1
,我猜:
Constructed objects ([dcl.init]) with static storage duration are destroyed and functions registered with std::atexit are called as part of a call to std::exit ([support.start.term]). The call to std::exit is sequenced before the destructions and the registered functions.
我没有看到在析构函数中调用 std::exit
有任何直接限制。
旁注:请不要评论“这段代码不好”、“thou shalt not use destructors in global objects”(您可能不应该这样做)以及在评论中探讨 XY 问题。考虑这是一个好奇的学生提出的学术问题,他知道对他们的原始问题有更好的解决方案,但在探索 C++ 的广阔草地时偶然发现了这个怪癖。
If
std::exit
is called to end a program during the destruction of an object with static or thread storage duration, the program has undefined behavior.