any*_*ker 3 c++ exception setjmp
假设我有一些 C++ 代码,其中有一个 try-catch 块,其中该catch部分将触发长跳转:
#include <stdexcept>
#include <stdio.h>
#include <setjmp.h>
void my_fun()
{
jmp_buf jump_buffer;
if (setjmp(jump_buffer))
return;
try {
std::string message;
message.resize(100);
snprintf(&message[0], 100, "error code %d\n", 3);
throw std::runtime_error(message);
}
catch (std::runtime_error &e) {
longjmp(jump_buffer, 1);
}
}
Run Code Online (Sandbox Code Playgroud)
由于该std::runtime_error对象是在某处动态分配的,因此它是否会泄漏为其或字符串分配的内存?
这有点复杂。关于longjmp\的有效性,标准说:
\n\n如果用 catch 和 throw 替换 setjmp 和 longjmp 会为任何具有自动存储持续时间的对象调用任何非平凡的析构函数,则 setjmp/longjmp 调用对具有未定义的行为。
\n
runtime_error有一个不平凡的析构函数,所以问题是异常对象是否具有“自动存储持续时间”。它不是。这表明longjmp应该没问题。
\n\n异常对象的潜在破坏点是:
\n\n
\n- \n
当异常的活动处理程序通过重新抛出以外的任何方式退出时,在处理程序中的异常声明中声明的对象(如果有)立即销毁后;
\n- \n
当指向异常对象的 std\xe2\x80\x8b::\xe2\x80\x8bexception_\xc2\xadptr 类型的对象被销毁时,在 std\xe2\x80\x8b::\xe2\x80 的析构函数之前\x8beException_\xc2\xadptr 返回。
\n
longjmp不是“重新抛出”。所以从理论上讲,由于要点 1,这应该没问题。
话虽如此,永远不要依赖这个。我非常怀疑 的实现是否longjmp正确处理了这个问题,即使有些实现,它也可能不是您所期望的。