2014-11-14 1 views
0

나는 EXCEPTION_CONTINUE_EXECUTION 이상한 behavour

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에 keyname을 추가하면 j가 수정되지 않았습니다.

+1

컴파일러에서 생성 한 어셈블리 코드를 살펴보십시오. 일반적인 C/C++ 제어 흐름에서 다른 값을 가질 수있는 방법이 없기 때문에 (1/s)의 s가 상수 0으로 처리 될 가능성이 큽니다. – arx

+0

어떤 컴파일러를 사용하고 있습니까? C++ 빌더를 사용하고 나에게 잘 돌아 간다면,'code1','code2','code4'를 예상대로 볼 수 있습니다. –

+0

Visual Studio 2008의 @RemyLebeau VC 컴파일러 – user1761982

답변

3

실행을 재개 할 때마다 예외가 다시 발생하기 때문에 무한 루프가 발생합니다. 트랩을 유발 한 명령 (이 경우 0으로 나누기)에서 실행이 재개되기 때문에 필터에 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의 값을로드하는 명령어가 아닌 0으로 나누는 명령어. 단계는 다음과 같습니다.

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'를 사용해야 만합니다. –

0

마지막 부분은 herehere을 보면 자세한 내용은 다른

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

에서 전체를 둘러싸는 실행하려고합니다.

'코드 2'인 행은 표시되지 않습니다. 이전 행의 예외로 인해 실행이 중단 되었기 때문입니다.

+0

예, 저는 __finally에 대해 알고 있지만, 이제는 __try ... __except (코드)를 배웁니다. code = 0 또는 1 일 때, 내 프로그램은 잘 작동하지만 code = EXCEPTION_CONTINUE_EXECUTION 일 때는 이상합니다. 사실, 내가 작동 할 때 코드 예제를 작성하려고합니다. – user1761982

+2

CONTINUE_EXECUTION은 오류를 수정하고 (s = 1, i) 시도한 것으로 가정합니다. 여기서 어셈블리 번역을 확인하여 실제로 어떤 일이 발생하는지 확인합니다. 어셈블리 수준에서 의도 된 의미를 그대로 유지한다고 가정 할 수는 없습니다. 이미 레지스터 또는 상수의 값으로 변환되었을 수 있습니다. – DNT