如何在c ++中处理中断信号并调用析构函数?

大宝剑*_*大宝剑 6 c++ destructor signals

可能重复:
如果发出SIGINT或SIGSTP,是否会调用析构函数?

我的代码是这样的:

#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正确处理 .但是人们永远不会知道;这样做会产生很大的运行时成本,而且通常不需要.)