관리 메뉴

Kim's Programming

구조적 예외처리 - SEH(Structured Exception Handling) 본문

Programming/System Programming

구조적 예외처리 - SEH(Structured Exception Handling)

Programmer. 2015. 12. 30. 20:18

하드웨어 예외와 소프트웨어 예외


구조적 예외는 하드웨어 예외(Hardware Exception)소프트웨어 예외(Software Exception)이 있습니다. 이중에서 하드웨어 예외는 하드웨어에서 인식하고 알려주는 예외를 의미합니다. 예를 들어서 div/0으로 나누는 것은 하드웨어 예외입니다. 다들 잘 모르고 있지만 0으로 나누는 연산은 CPU에서 연산오류입니다. 0으로 나누라는 연산 요청이 들어오면 문제가 있다는 신호를 신호를 운영체제에 전달합니다. 소프트웨어 예외는 프로그래머가 직접 정의할 수 있는 예외입니다. 만약 10이상의 숫자가 입력되었을 때는 예외처리하도록 하겠다. 라고 했으면 숫자 10이상을 예외시키는 것이 소프트웨어 예외입니다.


종료 핸들러(Termination Handler)


SEH에서는 성능을 조금 저하시켜서 서버에는 잘 사용되지 않지만 일반적인 프로그래밍에서는 컴퓨터 성능의 향상으로 SEH를 사용합니다. SEH는 예외처리 매커니즘은 기능적 특성에 따라서 2가지로 나뉩니다. 종료 핸들러(Termination Handler)와 예외 핸들러(Exception Handler)입니다. 우선 종료 핸들러 부터 알아보겠습니다.


종료 핸들러의 구성


종료 핸들러에서는 다음 두 키워드를 사용합니다. __try, __finally 두개를 사용합니다. __try문과 __finally 문은 다음과 같이 구성이 됩니다.

1
2
3
4
5
6
7
8
__try
{
    //코드 불록
}
__finally
{
    //예외 처리
}
cs

이 블록은 다음과 같이 해석됩니다. __try 블록에서 한 줄이라도 실행하게 되면 반드시 __finally 블록을 실행합니다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<tchar.h>
#include<Windows.h>
 
int _tmain(int argc, TCHAR *argv[])
{
    int a, b;
    __try
    {
        _tprintf(_T("Input Divide String [ a / b ] : "));
        _tscanf(_T("%d / %d"), &a, &b);
 
        if (b == 0)
            return -1;
    }
    __finally
    {
        _tprintf(_T("__finally blcok!\n"));
    }
    _tprintf(_T("result : %d \n"), a / b);
    return 0;
}
cs

실행해보면 다음과 같은 결과가 나오게 됩니다.


__try블록을 빠져나오는 상황이든 뭐든 간 __finally블록은 무조건 실행이 됩니다.

단, ExitProcess(), ExitThread(), exit()함수들에 의한 강제종료를 했을 시에는 finally로 이어지지는 않습니다.



예외 핸들러(Exception Handler)


종료 핸들러는 무조건 실행을 하게됩니다. 하지만 예외핸들러는 이외는 다르게 예외상황이 발생되었을때만 실행 되게 됩니다. 예외 핸들러를 사용할 때 코드는 다음과 같은 형태를 가지게됩니다.
1
2
3
4
5
6
7
8
__try
{
    //예외 발행
}
__except(예외처리 방식)
{
    //예외처리를 위한 코드 지역
}
cs

__try블록에서 예외 상황이 발생하면 그다음에 바로 있는 __except블록에서 이 상황을 처리하게 됩니다. 다음 예외사항을 처리하는 적절한 코드는 개발자가 구현해야합니다. 그리고 __except문에 예외처리 방식은 예외필터(Exception Filter)라고 하며 예최처리 매커니즘을 어떻게 동작시킬지 그 동작 방식을 결정하기위한 괄호입니다. 파라메터전달을 위한 부분은 아닙니다. 예외처리방식 괄호에는 다음 3개가 들어갈 수 있습니다.

1
2
3
4
5
6
7
EXCEPTION_EXCUTE_HANDLER
//예외처리루틴을 실행 여기서는 __except내의  코드를 실행
EXCEPTION_CONTINUE_EXECUTION
//예외가 발생한 라인부터 다시 시도하며 예외가 해결되지 않은 상황에서 
//실행하게 되면 무한 루프에 빠지게됨
EXCEPTION_CONTINUE_SEARCH
//try~catch문의 예외를 던지는 것과 같은 효과
cs


예외 핸들러중 EXCEPTION_EXCUTE_HANDLER을 이용한 소스를 작성해 보겠습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<tchar.h>
#include<Windows.h>
 
int _tmain(int argc, TCHAR *argv[])
{
    _tprintf(_T("Program Start!\n"));
    int *= NULL;
 
    __try
    {
        *= 300;//오류 발생
        _tprintf(_T("Value : %d\n"), *p);
    }
    __except (EXCEPTION_EXECUTE_HANDLER)
    {
        _tprintf(_T("Error Occured\n"));
    }
    _tprintf(_T("Program End\n"));
    return 0;
}
cs

try문 내에서 오류가 발생할때 그위치에서 바로 except 코드를 실행하게 됩니다. 따라서 다음과 같은 결과가 나오게됩니다.











'Programming > System Programming' 카테고리의 다른 글

프로세스 예제  (0) 2016.02.05
커널 오브젝트 그리고 Usage Count  (0) 2016.01.01
파일처리함수(2/2)  (0) 2015.12.25
파일처리함수(1/2)  (0) 2015.12.24
커널 오브젝트(Kernel Object)  (0) 2015.12.23