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

新手上路,请多包涵

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

原文由 SkypeMeSM 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 2.3k
2 个回答

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

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

这段代码展示了如何让信号正常退出程序,包括调用所有常用的析构函数:

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

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

void got_signal(int)
{
    // Signal handler function.
    // Set the flag and return.
    // Never do real work inside this function.
    // See also: man 7 signal-safety
    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;
}

如果你运行这个程序并按下 control-C,你应该会看到打印出的单词“destructor”。

请注意,您的信号处理函数(got_signal)应该很少做任何工作,除了设置一个标志并安静地返回,除非您真的知道自己在做什么。另见: https ://man7.org/linux/man-pages/man7/signal-safety.7.html

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

原文由 corecursion 发布,翻译遵循 CC BY-SA 4.0 许可协议

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

如果您想自己处理信号,请考虑查看 sigaction 标准库函数。

原文由 pr1268 发布,翻译遵循 CC BY-SA 2.5 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题