본문 바로가기

Windows/_Windows Programming

구조적 예외처리(SEH)

예외처리 :

개념 : 소스코드를 프로그램의 실제 흐름과 그 흐름에 대한 예외처리 영역을 나누어 작성하는것.


사용법 :

1. 종료 핸들러(Termination Handler) : 

예외가 발생하여 프로그램이 정상치 못하게 종료되더라도 메모리 반환등의 문제를 해결하기 위하여 사용


__try
{
             // 코드
}

__finally
{
             // 종료 처리
}

__try 블록을 한 줄이라도 실행하게 되면, 반드시 __finally 블록을 실행한다.
(참고 : __try 블록과 __finally 블록 사이에는 어느 문장도 올 수 없다. 반드시 __try 와 __finally 둘다 있어야 한다.


예)

#include <stdio.h>
#include <tchar.h>
#include <windows.h>

int _tmain(int argc, TCHAR *argv[])
{
          int num1, num2;
          
          __try
          {
                    _tprintf(_T("input divide a / b : "));
                    _scanf(_T("%d /%d"), &num1, &num2);
    
                    if(b==0)
                    {
                              return -1;
                    }
           }
           __finally
           {
                     _tprintf(_T("__finally block!\n"));
           }
     
           _tprintf(_T("result : %d \n"), num1/num2);
           return 0;
}

실행 결과 : 5, 0  입력 ->     input divide a / b                  5, 5 입력 ->   input divide a / b
                                       5 / 0                                                       5 / 5
                                       __finally block!                                         result : 1



2. 예외 핸들러와 필터(Exception Handler & Filters) :

__try
{
           // 예외 발생 경계 지역
}

__except(예외처리 방식) // EXCEPTION_EXECUTE_HANDLER ,      EXCEPTION_CONTINUE_EXECUTION
{
          // 예외 처리를 위한 코드 지역
}

__try 블록에서 예외상황이 발생하면  __except 블록에서 이 상황을 처리한다.
예외처리 방식(필터)에 의해 처리방식이 달라진다.
__except 블록의 예외필터를 구성할때 함수 호출문장이 올수 있으나 리턴값은 필터 표현식이어야 한다.


예) EXCEPTION_EXECUTE_HANDLE ( 건너 뛰기 )

예외가 발생하면 __except 구문의 예외를 처리한후 예외가 발생한 지점부터의 __try 블록을 건너뛰어 실행한다.

#include <stdio.h>
#include <tchar.h>
#include <windows.h>
int _tmain(int argc, TCAHR *argv[])
{
        _tprintf(_T("start point! \n"));
        
        int *p = NULL;

       __try
       {
               *p = 100;          // 예외발생지점.
               _tprintf(_T("value : %d \n"), *p);
       }
       __except(EXCEPTION_EXECUTE_HANDLER)
       {
               _tprintf(_T("exception occurred! \n"));
       }
 
       _tprintf(_T("end point! \n"));
       return 0;
}

실행과정 :
int *p = NULL;  *p = 100; *p에 NULL 값을 넣고 할당되지 않은 주소에 *p = 100 을 대입하고 있다. 예외가 발생한다.

start point! -> 예외발생 __except 문으로 이동(EXCEPTION_EXECUTE_HANDLE에 의해)하여 문장을 실행한다
exception occurred -> end point!

실행결과 : start point!
               exception occurred!
               end point!


예) EXCEPTION_CONTINUE_EXECUTION;

예외가 발생하면 __except 구문의 예외를 처리한후 예외가 발생한 지점 다음부터 실행한다.

#include <stdio.h>
#include <tchar.h>
#include <windows.h>
DWORD FilterFunction(DWORD exptType);

int _tmain(int argc, TCHAR *argv[])
{
         int num1, num2;

         __try
         {
                   while(1)
                  {
                          _tprintf(_T("input num1 / num2 : "));
                          _scanf(_T("%d / %d"), &num1, num2);
                          _tprintf(_T("result : %d"), num1/num2);                          
                  }
         }
         __except(FilterFunction( GetExceptionCode() ) )   // GetExceptionCode 로 얻어진 값을
         {                                                                     //  FilterFunction 의 인자로 전달
                 _tprintf(_T("__except block \n"));
         }
         return 0;
}

DWORD FilterFunction(DWORD exptType)
{
         switch(exptType)
         {
                  case EXCEPTION_INT_DIVIDE_BY_ZERO:
                          _tprintf(_T("Not input 0, Try Second Number : "));
                          _tscanf(_T("%d"), &num2);
                          return EXCEPTION_CONTINUE_EXECUTION;
                  default:
                          return EXCEPTION_EXECUTE_HANDLER;
          }
}

실행결과 : 5, 0, 5 입력 ->      input num1 / num2
                                         5 / 0 
                                         Not input 0, Try Second Number : 5
                                         result : 1

(EXCEPTION_CONTINUE_EXECUTION 이 필터식일때는 __except 블록 내부를 실행하지 않는다)

'Windows > _Windows Programming' 카테고리의 다른 글

GetLastError() 함수  (2) 2010.02.10
Mstsc(원격) 사용하기  (4) 2010.02.06
리소스(Resource)  (0) 2009.12.24
윈도우 프로그램 기본 틀  (0) 2009.12.23
윈도우 관리 메시지  (0) 2009.12.23