如果发出SIGINT或SIGSTP,是否会调用析构函数?

Sky*_*eSM 34 c++ destructor sigint

我有一个用户定义的析构函数的类.如果最初实例化了类,然后在程序运行时发出了SIGINT(在unix中使用CTRL + C),那么是否会调用析构函数?SIGSTP的行为是什么(unix中的CTRL + Z)?

Sha*_*ugh 31

不,默认情况下,大多数信号会导致程序立即退出异常.

但是,您可以轻松更改大多数信号的默认行为.

此代码显示如何使信号正常退出程序,包括调用所有常用的析构函数:

#include <iostream>
#include <signal.h>
#include <unistd.h>
#include <cstring>
#include <atomic>

std::atomic<bool> quit(false);    // signal flag

void got_signal(int)
{
    quit.store(true);
}

class Foo
{
public:
    ~Foo() { std::cout << "destructor\n"; }
};

int main(void)
{
    struct sigaction sa;
    memset( &sa, 0, sizeof(sa) );
    sa.sa_handler = got_signal;
    sigfillset(&sa.sa_mask);
    sigaction(SIGINT,&sa,NULL);

    Foo foo;    // needs destruction before exit
    while (true)
    {
        // do real work here...
        sleep(1);
        if( quit.load() ) break;    // exit normally after SIGINT
    }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

如果您运行此程序并按control-C,您应该看到打印出"析构函数"一词.请注意,除了设置标志并安静地返回之外,您的信号处理函数(got_signal)应该很少做任何工作,除非您真的知道自己在做什么.

大多数信号都可以捕获,如上所示,但不是SIGKILL,你无法控制它,因为SIGKILL是用于杀死失控进程的最后一种方法,而不是SIGSTOP,它允许用户冻结进程冷.请注意,如果需要,您可以捕获SIGTSTP(control-Z),但如果您对信号的唯一兴趣是析构函数行为,则不需要,因为最终在控制-Z之后,进程将被唤醒,将继续运行,并且将正常退出所有析构函数生效.

  • IIRC,正确的`quit`类型应该是`volatile std :: sig_atomic_t`.为此目的使用`bool`是UB. (5认同)
  • 我实际上得到了这个代码的错误:`使用已删除的函数`为`quit = false`行.你必须做`quit(false)`而不是`quit = false`.另外值得注意的是,此代码在Windows上不起作用; 你必须使用`SetConsoleCtrlHandler()`. (3认同)

pr1*_*268 9

如果你自己不处理这些信号,那么,不,不会调用析构函数.但是,操作系统将回收程序终止时使用的所有资源.

如果您希望自己处理信号,请考虑检查sigaction标准库函数.

  • 回收操作系统拥有的资源.在应用程序中还有其他其他资源,它们通常以这样的方式包装,即需要正确关闭它们(否则会损坏资源(如未正确终止的文件)). (3认同)

Sté*_*hen 7

Let's try it:

#include <stdio.h>
#include <unistd.h>

class Foo {
public:
  Foo() {};
  ~Foo() { printf("Yay!\n"); }
} bar;

int main(int argc, char **argv) {
  sleep(5);
}
Run Code Online (Sandbox Code Playgroud)

And then:

$ g++ -o test ./test.cc 
$ ./test 
^C
$ ./test 
Yay!
Run Code Online (Sandbox Code Playgroud)

So I'm afraid not, you'll have to catch it.

As for SIGSTOP, it cannot be caught, and pauses the process until a SIGCONT is sent.