如果在全局对象的析构函数中调用 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.1std::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++ 的广阔草地时偶然发现了这个怪癖。

[basic.start.main]/4:

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.