从 main 中抛出,即未捕获 SIGSEGV 中的异常结果

问题描述 投票:0回答:1

给出代码

#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 平台上它被允许或认为它必须终止带有 SIGSEGV 信号。据我了解,预计会出现 SIGABRT。

c++ linux language-lawyer c++20
1个回答
0
投票

这是编译器资源管理器的产物。

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

即使在编译器资源管理器上,您也可以处理

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
© www.soinside.com 2019 - 2024. All rights reserved.