我有一些奇怪的自修改代碼,但它的根源是一個非常簡單的問題:我希望能夠執行一個jmp
(或一個call
),然後從該任意點拋出一個異常,並使其被包含jmp
/call
的try/catch塊捕獲。內聯asm跳轉後拋出一個C++異常
但是,當我這樣做時(在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中的信號處理程序的上下文中提出過類似的問題。這真的只是籠罩了這個問題,所以我刪除了那個,問了這個更簡化的版本。整個信號處理器只是掩蓋了我真正的問題。 – SoapBox 2010-04-15 02:39:39
大致有兩種不同的方式來實現異常處理。一個是裝飾代碼和調用網站,以便在任何地方推動上下文,另一個是索引呼叫和返回點,以便異常處理程序可以查找去哪裏。無論哪種方式,內聯asm缺少一些東西。 – spraff 2012-02-03 15:19:06