Given the code

#include <iostream>
#include <stdexcept>

class Test {
public:
    Test() { std::cout << "Constructor called" << std::endl; }
    ~Test() { std::cout << "Destructor called" << std::endl; }
};

int main() {
    Test obj1;

    try 
    {
        Test obj2;
        throw std::runtime_error("Exception thrown"); 
    } // Object 2 is destroyed here
    catch (...)
    {
        throw; // std::abort
    }
} // not reached (implementation defined), Object 1 destructor never called

我明白为什么不调用obj2的析构函数,因为如果在未捕获的异常的情况下发生堆栈展开,它就是定义的实现,但我不明白为什么在通常的Linux platforms it's allowed or thinks it has to terminate with a SIGSEGV signal上.据我了解,预计会出现SIGABRT.

推荐答案

这是一个人造品(/bug?)更轻松的探险家.SIGABRT变成SIGSEGV:https://github.com/compiler-explorer/compiler-explorer/issues/5224

在我的计算机上运行它会显示:

$ ./example ; echo "Program returned: $?"
Constructor called
Constructor called
Destructor called
terminate called after throwing an instance of 'std::runtime_error'
  what():  Exception thrown
Aborted
Program returned: 134

即使在Ensemer Explorer上,您也可以处理SIGABRT来查看它是否仍然存在,后面只有一个SIGSEGV:https://godbolt.org/z/6dYsP5K5K

std::signal(SIGABRT, [](int) {
    std::cout << "Caught SIGABRT\n" << std::flush;
});
std::signal(SIGSEGV, [](int) {
    std::cout << "Caught SIGSEGV\n" << std::flush;
    std::_Exit(1);
});

更简单的资源管理器输出:

Program returned: 1
terminate called after throwing an instance of 'std::runtime_error'
  what():  Exception thrown
Constructor called
Constructor called
Destructor called
Caught SIGABRT
Caught SIGSEGV

我的电脑:

$ ./example ; echo "Program returned: $?"
Constructor called
Constructor called
Destructor called
terminate called after throwing an instance of 'std::runtime_error'
  what():  Exception thrown
Caught SIGABRT
Aborted
Program returned: 134

Linux相关问答推荐

抛出主,即未捕获到SIGSEGV中的异常结果

PERF显示不应该执行指令的内核的用户空间周期

2023 年如何在现代 Linux 上安装 Firebird SQL 版本 3 或 4?

替换前 3 个字符范围内的所有整数

操作系统信号处理循环 - 阻塞或非阻塞读取?

我需要制作一个 awk 脚本来解析文件中的文本.我不确定我是否做得正确

如何恢复已停止的进程?

如何在python中检索进程开始时间(或正常运行时间)

Bash 变量:是否区分大小写?

来自远程主机的 mysqldump

按主机名的 IPv6 地址

无法创建Java虚拟机

在 C 中检测 64 位编译

如何在 Ubuntu 12.04 中更改 Jenkins 安装的端口号

如何在 Bash 中对齐空格分隔表的列?

bash shell 脚本函数定义(如f () {})中使用的括号是什么?它与使用function关键字不同吗?

在 Linux 上的进程之间传递消息的最快技术?

如何使用 Ansible 等待服务器重启?

如果关键字触发然后执行命令,Shell 脚本来监视日志(log)文件?

在linux中将制表符分隔的文件转换为csv的最快方法