xml*_*lmx 24 c++ destructor global-variables thread-local-storage c++11
#include <cstdlib>
#include <thread>
#include <chrono>
#include <iostream>
using namespace std;
using namespace std::literals;
struct A
{
int n_ = 0;
A(int n) : n_(n) { cout << "A:" << n_ << endl; }
~A() { cout << "~A:" << n_ << endl; }
};
A a1(1);
int main()
{
std::thread([]()
{
static A a2(2);
thread_local A a3(3);
std::this_thread::sleep_for(24h);
}).detach();
static A a4(4);
thread_local A a5(5);
std::this_thread::sleep_for(1s);
std::exit(0);
}
Run Code Online (Sandbox Code Playgroud)
我的编译器是clang 5.0用-std=c++1z.
输出如下:
Run Code Online (Sandbox Code Playgroud)A:1 A:2 A:4 A:5 A:3 ~A:5 ~A:2 ~A:4 ~A:1
请注意,没有~A:3,这意味着对象A a3没有被破坏.
但是,根据cppref:
std::exit导致正常的程序终止发生.执行了几个清理步骤:保证调用具有线程本地存储持续时间...的对象的析构函数.
Rei*_*ica 38
具有线程存储持续时间的对象保证仅针对调用的线程销毁exit.引用C++ 14(N4140),[support.start.term] 18.5/8(强调我的):
Run Code Online (Sandbox Code Playgroud)[[noreturn]] void exit(int status)该功能
exit()在本国际标准中有其他行为:
- 首先,销毁具有线程存储持续时间并与当前线程相关联的对象.接下来,销毁具有静态存储持续时间的对象,并调用通过调用atexit注册的函数.有关破坏和调用的顺序,请参见3.6.3.(自动对象不会因调用而被销毁
exit().)如果控件离开了一个被调用的注册函数,exit因为该函数没有为抛出异常提供处理程序,std::terminate()则应调用(15.5.1).- 接下来,
<cstdio>刷新所有打开的C流(由声明的函数签名调解)和未写入的缓冲数据,关闭所有打开的C流,并tmpfile()删除通过调用创建的所有文件 .- 最后,控制权返回给主机环境.如果status为零
EXIT_SUCCESS,则返回状态成功终止的实现定义形式.如果status为EXIT_FAILURE,则返回状态为不成功终止的实现定义形式.否则返回的状态是实现定义的.
因此,该标准不保证具有与其他线程相关联的线程存储持续时间的对象的销毁exit.
Som*_*ude 15
这里的问题是当你退出进程时,线程将(在大多数现代多任务操作系统上)被强行杀死.这种线程的查杀发生在操作系统级别,操作系统对对象或析构函数一无所知.