2014-11-14 96 views
0

我寫代碼EXCEPTION_CONTINUE_EXECUTION奇怪水煤漿

void SEHtest(int i) { 
    int s = 0; 
    __try { 
    cout << "code1" << endl; 
    int j = 1/s; 
    cout << "code2" << endl; 
    } __except((s = 1, i)) { 
    cout << "code3" << endl; 
    } 
    cout << "code4" << endl; 
    return; 
} 
int main() { 
    SEHtest(-1); 
    return 0; 
} 

,我等待輸出

code1 
code2 
code4 

,但我只有

code1 

和無限循環。

爲什麼?

加入volatile鍵名到s和j沒有修復它。

+1

查看編譯器生成的彙編代碼。很可能(1/s)中的s被視爲一個常量零,因爲在正常的C/C++控制流程中沒有任何其他值。 – arx 2014-11-14 18:01:03

+0

你使用什麼編譯器?我使用C++ Builder,並且你所顯示的對我來說工作正常,我可以按預期的方式看到'code1','code2'和'code4'。 – 2014-11-14 18:04:46

+0

@RemyLebeau來自Visual Studio 2008的VC編譯器 – user1761982 2014-11-14 18:22:40

回答

3

無限循環是由於每次恢復執行時重新拋出異常而導致的。無需在過濾器中設置值s = 1,因爲從導致陷阱的指令恢復執行,在這種情況下,該指令除以零。如果您整理如下代碼,你會看到,除了不斷被拋出:

int ExceptionFilter(int& s) { 
    cout << "exception filter with s = " << s << endl; 
    s++; 
    return -1; // EXCEPTION_CONTINUE_EXECUTION 
} 

void SEHtest() { 
    int s = 0; 
    __try { 
    cout << "before exception" << endl; 
    int j = 1/s; 
    cout << "after exception" << endl; 
    } __except(ExceptionFilter(s)) { 
    cout << "exception handler" << endl; 
    } 
    cout << "after try-catch" << endl; 
    return; 
} 

int main() { 
    SEHtest(); 
    return 0; 
} 

的結果應改爲:

before exception 
exception filter with s = 0 
exception filter with s = 1 
exception filter with s = 2 
... 

異常繼續拋出,因爲執行的恢復指令除以零,而不是加載s值的指令。步驟是:

1 set a register to 0 
2 store that register in s (might be optimized out) 
3 enter try block 
4 output "before exception" 
5 load a register from s 
6 divide 1 by register (trigger exception) 
7 jump to exception filter 
8 in filter increment/change s 
9 filter returns -1 
10 execution continues on line 6 above 
6 divide 1 by register (trigger exception) 
7 jump to exception filter 
8 in filter increment/change s 
9 filter returns -1 
10 execution continues on line 6 above 
... 

我不認爲你能從這個例外恢復。

+0

如果您知道哪個寄存器用於除法,您將能夠恢復,並調整該寄存器的值而不是調整's'變量。但是這要求您對某些編譯器爲此代碼生成機器指令有一些深入的瞭解。在這個特定的例子中,代碼應該使用'EXCEPTION_EXECUTE_HANDLER'來處理異常並繼續前進。 – 2014-11-14 18:59:00

0

如果你想在最後一部分來執行試圖包圍了整個事情的另一

__try { 
< your code> 
} 
__finally{ 
    < code that will be executed at end> 
} 

欲瞭解更多信息,看看herehere

帶'code 2'的行不會顯示,因爲執行被上一行的異常中斷。

+0

是的,我知道__finally,但現在我學習__try ... __except(code)。當代碼= 0或1時,我的程序工作正常,但是當代碼= EXCEPTION_CONTINUE_EXECUTION時很奇怪。實際上,我試着寫一個代碼的例子 – user1761982 2014-11-14 17:54:16

+2

CONTINUE_EXECUTION假設你做了一些事情來解決這個錯誤,而你試圖在(s = 1,i)中進行嘗試。在這裏,我會檢查彙編翻譯以查看真正發生的事情。你不能假設'''在彙編級保留了預期的語義。它可能已經被翻譯爲一個寄存器或常量的值。 – DNT 2014-11-14 18:00:58