大宝剑*_*大宝剑 6 c++ destructor signals
我的代码是这样的:
#include <iostream>
#include <signal.h>
#include <cstdlib>
void handler(int) {
std::cout << "will exit..." << std::endl;
exit(0);
}
class A {
public:
A() {std::cout << "constructor" << std::endl;}
~A() {std::cout << "destructor" << std::endl;}
};
int main(void) {
signal(SIGINT, &handler);
A a;
for (;;);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
当我按下Ctrl-C时,它打印出:
constructor
^Cwill exit...
Run Code Online (Sandbox Code Playgroud)
没有打印出"析构函数".那么,我怎样才能干净利落地出境呢?
Jam*_*nze 11
有困难.您编写的代码已经有了未定义的行为; 你不能输出信号处理程序中的流; 就此而言,你也不允许打电话exit.(我的断言基于Posix标准.在纯C++中,你所允许做的就是分配一个sig_atomic_t类型的变量.)
在类似代码的简单情况下,您可以执行以下操作:
sig_atomic_t stopFlag = 0;
void
handler( int )
{
stopFlag = 1;
}
int
main()
{
signal( SIGINT, &handler );
A a;
while ( stopFlag == 0 ) {
}
std::cout << "will exit..." << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
根据应用程序的不同,您可以执行以下操作,stopFlag在适当的位置进行检查.但一般来说,如果你试试这个,就会出现竞争条件:你stopFlag在开始一个可中断的系统调用之前检查,然后进行调用; 信号到达检查和呼叫之间,你进行呼叫,并且不会中断.(我已经使用过这种技术,但在一个应用程序中,唯一可中断的系统调用是一个读取时间非常短的套接字.)
通常,至少在Posix下,你最终必须创建一个信号处理线程; 这可以用于干净地关闭所有其他线程.基本上,您首先设置信号掩码以阻止所有信号,然后在信号处理线程中,一旦启动,将其设置为接受您感兴趣的信号并进行呼叫sigwait().但是,这意味着您要执行干净关闭线程所需的所有常用操作:信号处理线程必须知道所有其他线程,调用pthread_cancel它们等,并且您需要编译器生成正确处理代码pthread_cancel,或者您需要开发一些其他方法来确保正确通知所有线程.(今天,人们希望所有编译器都能pthread_cancel正确处理
.但是人们永远不会知道;这样做会产生很大的运行时成本,而且通常不需要.)