yep*_*ons 21 c++ destructor terminate language-lawyer
考虑以下代码:
\n#include <cstdlib>\nstruct Foo {\n ~Foo() {\n std::exit(0);\n }\n} foo;\nint main() {\n}\nRun Code Online (Sandbox Code Playgroud)\n它在我的 Linux(GCC、Clang)和 Windows(Visual Studio)上都成功编译并以零终止。然而,当在Windows()上用MSYS2的GCC编译时g++ (Rev2, Built by MSYS2 project) 10.3.0,它会进入无限递归并因堆栈溢出而死亡。这可以通过在之前添加一些调试输出来检查std::exit();我最初没有添加它是为了避免考虑破坏std::cout.
是否有任何 C++ 标准对这种行为有任何规定?它是否定义良好/实现定义/未定义/等等,为什么?
\n例如,最近的一些草案对\ 的行为[support.start.term]/9.1进行了以下说明:std::exit
\n\n首先,销毁与当前线程关联的具有线程存储持续时间的对象。\n接下来,销毁具有静态存储持续时间的对象,并调用通过调用 atexit 注册的函数。有关销毁和调用的顺序,请参阅 [basic.start.term]。
\n
[basic.start.term]/1我猜它指的是:
\n\n具有静态存储持续时间的构造对象([dcl.init])将被销毁,并且在 std\xe2\x80\x8b::\xe2\x80\x8batexit 中注册的函数将作为 std\xe2\x80\x8b 调用的一部分被调用: :\xe2\x80\x8bexit ([support.start.term])。\n对 std\xe2\x80\x8b::\xe2\x80\x8bexit 的调用在销毁和注册函数之前排序。
\n
我没有看到对std::exit析构函数调用有任何直接限制。
旁注:请不要评论“这段代码很糟糕”、“你不应该在全局对象中使用析构函数”(你可能不应该)并在评论中探究 XY 问题。将此视为一个好奇的学生提出的学术问题,他知道对原始问题有更好的解决方案,但在探索 C++ 的广阔领域时偶然发现了这个怪癖。
\nLan*_*yer 43
\n\n\n如果
\nstd\xe2\x80\x8b::\xe2\x80\x8bexit在销毁具有静态或线程存储持续时间的对象期间调用来结束程序,则该程序具有未定义的行为。
| 归档时间: |
|
| 查看次数: |
1905 次 |
| 最近记录: |