【发布时间】:2011-12-30 00:25:54
【问题描述】:
我需要在运行时生成执行以下操作的代码:
auto v_cleanup = std::shared_ptr<void>(nullptr, [](void *){ cleanup(); });
//...
do_some_danger_thing();
//...
或 C 等价物:
__try {
//...
do_some_danger_thing();
//...
} __finally {
cleanup();
}
cleanup() 函数保证没有异常,但是 do_some_danger_thing() 可能会抛出异常。此运行时代码必须不使用堆栈,这意味着在调用 do_some_danger_thing() 时,堆栈必须处于与我们进入运行时代码时相同的状态,除了返回地址设置为运行时代码(原始值保存到“jmp " 目标,为了返回给调用者)。
因为我们使用的是动态机器码,所以目标平台在 x86 CPU 上固定为 WIN32,x64 CPU 目前不在焦点范围内。
为此,我们必须处理任何异常。在 WIN32 C++ 中,异常是基于 SEH 的,所以我们必须处理它。问题是我们无法找到一种方法来做到这一点并使其与其他代码兼容。我们尝试了几种解决方案,但都不起作用,有时用户安装的异常处理程序从未被调用,有时外部异常处理程序被绕过,我们收到“未处理的异常”错误。
更新:
似乎 SEH 异常处理程序链仅支持 EXE 映像中的代码。如果异常处理程序指向我生成的代码,它将永远不会被调用。我要做的就是创建一个静态异常处理函数stub,然后让它调用生成的处理函数。
【问题讨论】:
-
这两个代码 sn-ps 不一样 - 一方面,如果抛出异常,您的第一个 sn-p 只会调用 cleanup();您的第二个 sn-p 将始终调用它。另外,为什么没有堆栈,或者它可以恢复,或者......?为什么要实现自己的异常处理?我认为这个问题需要更多关于您要实现的目标的详细信息。请说明您这样做的目的、原因等。
-
你是正确的代码 sn-ps... 我会修复它。对于您关于“为什么要实现自己的”的问题,我相信我已经解释过:我将在运行时生成机器代码,异常处理只是故事的一部分。是的,您可以在调用 do_some_danger_thing 之前恢复堆栈,如果您决定这样做,您必须支付更多生成代码的成本。