#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。
这是编译器资源管理器的产物。
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