예외 처리기 사용
다음 예는 예외 처리기의 사용을 보여 줍니다.
예 1
다음 코드 조각은 구조적 예외 처리를 사용하여 두 개의 32비트 정수에 대한 나누기 연산으로 인해 0으로 나누기 오류가 발생하는지 여부를 확인합니다. 이 경우 함수는 FALSE를 반환하고 그렇지 않으면 TRUE를 반환합니다.
BOOL SafeDiv(INT32 dividend, INT32 divisor, INT32 *pResult)
{
__try
{
*pResult = dividend / divisor;
}
__except(GetExceptionCode() == EXCEPTION_INT_DIVIDE_BY_ZERO ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
{
return FALSE;
}
return TRUE;
}
예제 2
다음 예 함수는 DebugBreak 함수를 호출하고 구조화된 예외 처리를 사용하여 중단점 예외를 확인합니다. 하나가 발생하면 함수는 FALSE를 반환하고 그렇지 않으면 TRUE를 반환합니다.
예의 필터 식은 GetExceptionCode 함수를 사용하여 처리기를 실행하기 전에 예외 형식을 확인합니다. 이렇게 하면 다른 형식의 예외가 발생하는 경우 시스템이 적절한 처리기를 계속 검색할 수 있습니다.
또한 예외 처리기의 __try 블록에서 return 문을 사용하는 것은 종료 처리기의 __try 블록에서 return을 사용하는 것과 다르며, 이로 인해 __try 블록이 비정상적으로 종료됩니다. 이는 예외 처리기에서 return 문을 올바르게 사용하는 것입니다.
BOOL CheckForDebugger()
{
__try
{
DebugBreak();
}
__except(GetExceptionCode() == EXCEPTION_BREAKPOINT ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
{
// No debugger is attached, so return FALSE
// and continue.
return FALSE;
}
return TRUE;
}
예외 형식이 예상되고 오류 주소가 알려진 경우에만 예외 필터에서 EXCEPTION_EXECUTE_HANDLER를 반환합니다. 기본 예외 처리기가 예기치 않은 예외 형식 및 오류 주소를 처리하도록 허용해야 합니다.
예제 3
다음 예는 중첩 처리기의 상호 작용을 보여 줍니다. RaiseException 함수는 예외 처리기의 보호된 본문 내부에 있는 종료 처리기의 보호된 본문에서 예외를 발생시킵니다. 예외로 인해 시스템은 FilterFunction 함수를 평가하게 되며, 이 함수의 반환 값은 예외 처리기를 호출하게 합니다. 그러나 예외 처리기 블록이 실행되기 전에 제어 흐름이 종료 처리기의 __try 블록을 떠났기 때문에 종료 처리기의 __finally 블록이 실행됩니다.
DWORD FilterFunction()
{
printf("1 "); // printed first
return EXCEPTION_EXECUTE_HANDLER;
}
VOID main(VOID)
{
__try
{
__try
{
RaiseException(
1, // exception code
0, // continuable exception
0, NULL); // no arguments
}
__finally
{
printf("2 "); // this is printed second
}
}
__except ( FilterFunction() )
{
printf("3\n"); // this is printed last
}
}