提问人:yeputons 提问时间:10/27/2021 最后编辑:Boannyeputons 更新时间:10/28/2021 访问量:1874
如果在全局对象的析构函数中调用“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)上都成功地编译并以零成功终止。但是,当在 Windows 上使用 MSYS2 的 GCC 编译时 (),它会进入无限递归并因堆栈溢出而死亡。这可以通过在 ;我最初没有添加它,以避免考虑 .g++ (Rev2, Built by MSYS2 project) 10.3.0
std::exit()
std::cout
是否有任何 C++ 标准对这种行为有什么要说的?它是否定义明确/实现定义/未定义/等,为什么?
例如,最近的一些草案对 的行为说了以下几点:[support.start.term]/9.1
std::exit
首先,销毁具有线程存储持续时间并与当前线程关联的对象。 接下来,销毁具有静态存储持续时间的对象,并调用通过调用 atexit 注册的函数。请参阅 [basic.start.term] 了解销毁和调用的顺序。
指的是,我猜:[basic.start.term]/1
具有静态存储持续时间的构造对象 ([dcl.init]) 将被销毁,向 std::atexit 注册的函数将作为对 std::exit ([support.start.term]) 的调用的一部分调用。 对 std::exit 的调用在销毁和注册函数之前进行排序。
我没有看到对调用析构函数的任何直接限制。std::exit
旁注:请不要评论“此代码不好”、“你不应该在全局对象中使用析构函数”(你可能不应该这样做)并在评论中探究 XY 问题。考虑这是一个来自好奇学生的学术问题,他知道他们原始问题的更好解决方案,但在探索广阔的C++草地时偶然发现了这个怪癖。
答:
如果在销毁具有静态或线程存储持续时间的对象期间调用以结束程序,则该程序具有未定义的行为。
std::exit
评论
atexit
exit
atexit
评论
atexit()