【发布时间】:2010-04-15 02:30:29
【问题描述】:
我有一些奇怪的自我修改代码,但其根源是一个非常简单的问题:我希望能够执行 jmp(或 call)然后从那个任意点抛出异常并让它被包含jmp/call 的try/catch 块捕获。
但是当我这样做时(在 gcc 4.4.1 x86_64 中),异常会导致 terminate(),就像从 try/catch 之外抛出异常一样。我真的不明白这与从某个遥远的库中抛出异常有何不同,但这显然是因为它不起作用。
如何执行jmp 或call 但仍将异常抛出回原来的try/catch?为什么这个 try/catch 不能像正常调用函数一样继续处理这些异常?
代码:
#include <iostream>
#include <stdexcept>
using namespace std;
void thrower()
{
cout << "Inside thrower" << endl;
throw runtime_error("some exception");
}
int main()
{
cout << "Top of main" << endl;
try {
asm volatile (
"jmp *%0" // same thing happens with a call instead of a jmp
:
: "r"((long)thrower)
:
);
} catch (exception &e) {
cout << "Caught : " << e.what() << endl;
}
cout << "Bottom of main" << endl << endl;
}
预期输出:
Top of main
Inside thrower
Caught : some exception
Bottom of main
实际输出:
Top of main
Inside thrower
terminate called after throwing an instance of 'std::runtime_error'
what(): some exception
Aborted
【问题讨论】:
-
最初我在 linux 中的信号处理程序上下文中问了一个类似的问题。那真的只是让问题变得模糊不清,所以我删除了那个并询问了这个更简化的版本。整个信号处理程序只是掩盖了我真正的问题。
-
实现异常处理的方式大致有两种。一种是修饰代码和调用站点,以便到处推送上下文,另一种是索引调用和返回点,以便异常处理程序可以查找到哪里。无论哪种方式,内联汇编都缺少一些东西。