2013-02-26 2 views
2

SEH로 몇 가지 실험을하고있었습니다. 내 코드에서 __try 절의 블록과 __except()의 핸들러 오류를 작성했습니다.SEH (구조적 예외 처리)를 사용할 때 다른 동작이 발생했습니다.

__try{ 
Test *pTest = 0; 
int k = pTest->GetValue(); 
cout << "continue after exception" << endl; 
} 
__except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION,EXCEPTION_EXECUTE_HANDLER) 
{ 
cout << "caught!!" << endl; 
} 
cout << "Exception handled" << endl; 

두번째 파라미터 __except하는()는 다음 중 어느 하나 인 -

EXCEPTION_CONTINUE_SEARCH 예외가 인식되지 않는다. 먼저 try-except 문을 포함하는 핸들러를 검색 한 다음 우선 순위가 높은 핸들러를 검색합니다.

EXCEPTION_CONTINUE_EXECUTION 예외는 인식되지만 무시됩니다. 예외가 발생한 지점에서 계속 실행하십시오.

EXCEPTION_EXECUTE_HANDLER 예외가 인식됩니다. __except 복합 문을 실행하여 예외 처리기로 제어를 전송 한 다음 예외가 발생한 지점에서 실행을 계속합니다.

EXCEPTION_CONTINUE_EXECUTION/EXCEPTION_EXECUTE_HANDLER를 사용할 때 예외 발생 지점에서 계속 실행되지 않습니다 (예외 발생 지점의 의미를 잘못 해석하고있는 것일 수 있음). 내가 디버그 모드에서 실행하면 내가 릴리스 모드에서 실행하면 는, 출력이

caught 
Exception handled 

이며, 출력은 다르게 행동하는 이유를 나는 이해할 수 없었다

continue after exception 
Exception handled 

입니다. 누구든지 도와주세요.

+0

GetValue() 메소드의 내용보기 – ixSci

+0

'Test'의 정의를 보여주고 SEH와 C++ 예외와 관련하여 디버그 옵션과 릴리즈 옵션이 어떻게 다른지 보여줍니다. 옵션이 있습니다. 또는 release 모드에서'__try {}'블록의 디스 어셈블리를 더 잘 보여줍니다. 그것은 더 나은 단서가있을 수 있습니다. –

+0

''pTest'는 클래스에 대한 포인터이며'GetValue()'를 실행하기 위해 역 참조 할 필요가 없으며 컴파일러는 최적화가 릴리스 모드에서 활성화되면이를 인식합니다. 아니면 GetValue()를 쓸모없는 것으로 간주하고 호출 할 코드를 생성하지 않습니다. 또한 컴파일러가 NULL 포인터를 역 참조하면 정의되지 않은 동작이 발생하고 컴파일 타임에 코드를 조작하여이를 처벌하기로 결정할 수도 있습니다. 모든 권한이 있습니다. 'gcc'는 그것을하는 것으로 악명 높다. –

답변

4

@Joachim 쉼표 연산자 문제에 대해 정확하게 지적한다.

__except((GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION) ? 
     EXCEPTION_EXECUTE_HANDLER : 
     EXCEPTION_CONTINUE_SEARCH) 

이 예외가 액세스 위반 인 경우 예외 핸들러가 실행하게됩니다 :

은 내가 __except()은 다음과 같이한다 생각합니다. 그렇지 않은 경우, 가장 가까운 바깥 쪽 __try까지 예외가 전파됩니다.

GetValue()을 실행하기 위해 pTest이 클래스를 가리키는 포인터가 아니므로 역 참조 할 필요가 없으며 컴파일러는 최적화가 릴리스 모드에서 활성화되었을 때이를 인식합니다. 또는 심지어 GetValue()이 쓸데없는 것으로 간주하고 코드를 호출하지 않습니다. 또한 컴파일러가 NULL 포인터를 역 참조하면 정의되지 않은 동작이 발생하고 컴파일 타임에 코드를 조작하여이를 처벌하기로 결정할 수도 있습니다. 모든 권한이 있습니다. gcc는이를 수행하는 것으로 유명합니다.

+0

귀하의 조언에 따라 코드를 편집했습니다. 그러나 잡힌 예외도 EXCEPTION_ACCESS_VIOLATION입니다. "catch!"라는 문자열을 표시하지 않습니다. 해제 모드에서 –

1

표현

GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION,EXCEPTION_EXECUTE_HANDLER 

은 당신이에 기대하지 않습니다. 그것이하는 것은 GetExceptionCode()의 결과를 EXCEPTION_ACCESS_VIOLATION으로 비교하지만 전체 표현의 결과는 EXCEPTION_EXECUTE_HANDLER입니다.

쉼표 연산자에 대한 자세한 내용은 at Wikipedia을 참조하십시오. 당신이 원하는 무엇

아마입니다 :

GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION || GetExceptionCode() == EXCEPTION_EXECUTE_HANDLER 
+0

'GetExceptionCode()'는'EXCEPTION_EXECUTE_HANDLER'을 반환하지 않습니다. –

+0

답변을 주신 Joachim에게 감사드립니다. 하지만 디버그/릴리스 모드에서 다르게 동작하는 이유는 아직 알 수 없습니다. –