(Win32 : WindowsProgramming-21) Structed Exception

Posted by : at

Category : win32   WindowsProgramming


구조화된 예외

#include <stdio.h>
#include <Windows.h>

int main()
{
    int n = 0

    int s = 10 / 0;     // (컴파일러가 똑똑해 져서) 컴파일 에러 발생
}
int main()
{
    int n = 0

    int s = 10 / n;     // 런타임에 에러
}

런타임 에러가 발생하는 기전은
기게어 코드에서 문제발생 -> CPU에 통보 -> Windows OS에 통보 -> IDE에 Exception을 전달

  • C++에서 제공하는 예외가 아니라 Windows OS에서 제공하는 예외이다.
    • __try{} __except{}를 이용해 예외를 잡아보자
int main()
{
    int n = 0

    // 아래와 같은 방식으로 Windows OS exception을 잡을 수 있다.
    __try
    {
        int s = 10 / n;
    }
    __except(1)
    {
        // 왜 죽었는지 확인방법
        printf("exception : %x\n", GetExceptionCode());
    }
}
  • __except()는 에 들어갈수 있는 매개변수는 세 가지이다.
    • EXCEPTION_EXECUTE_HANDER(1) : 일반적 예외
    • EXCEPTION_CONTINUE_SEARCH(2) : except를 받았지만 일단은 처리하지 않고 다름 try를 찾아라
    • EXCEPTION_CONTINUE_EXECUTION(-1) : 다시 try문을 시도해라
int n = 0

DWORD Filter(DWORD code)
{
    if(code == EXCEPTION_INT_DEVIDE_BY_ZERO)
    {
        printf("divide by zero");
        n = 5;

        return EXCEPTION_CONTINUE_EXECUTION;    // 재시도 해보시오
    }

    printf("other exception\n");
    return EXCEPTION_EXECUTE_HANDER;
}

int main()
{
    __try
    {
        int s = 10 / n;
    }
    __except(Filter(GetExceptionCode()))
    {
        // 참고로 GetExceptionCode()는 except내부에서만 호출이 가능하지 다른 함수에서 호출이 불가능
        printf("exception : %x\n", GetExceptionCode());
    }
}

어느 레지스터에 발생했는지 확인 방법

예외 발생시 스택에 예외 정보가 추가된다.
GetExceptionInformation()을 통해 알 수있다.
단, GetExceptionInformation()__exceptp(/*여기*/)에서만 호출이가능하다
다른곳에서 호출 시 스택이 모두 지워진다.

#include <stdio.h>
#include <Windows.h>

DWORD Filter(EXCEPTION_POINTERS* ep)
{
    DWORD code = ep->ExceptionRecord->ExceptionCode;
    void* addr = ep->ExceptionRecord->ExceptionAddress;

    // ep->ContextRecord->Eip;

    return EXCEPTION_EXECUTE_HANDER;
}

int main()
{
    int n = 0;

    __try
    {
        int s = 10 / n;
    }
    __except(Filter(GetExceptionInformation())) 
    // GetExceptionInformation()는 __except의 매개변수로만 들어갈 수 있다는 점을 기억.
    {
        printf("exception : %x\n", GetExceptionCode());
    }
}

C++ 예외

class AAA
{
public:
    ~AAA() {}
};

int main()
{
    __try
    {
        // C++ 객체가 있으면 exception을 못잡음.
        // C++ 에서는 못쓴다는 말. 이후에 어떻게 사용될지 알려준다
        AAA aaa; // 디버그 에러
        char* p = 0;
        p = 0;  // Exception
    }
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
        printf("exceptin\n");
    }
}

About Taehyung Kim

안녕하세요? 8년차 현업 C++ 개발자 김태형이라고 합니다. 😁 C/C++을 사랑하며 다양한 사람과의 협업을 즐깁니다. ☕ 꾸준한 자기개발을 미덕이라 생각하며 노력중이며, 제가 얻은 지식을 홈페이지에 정리 중입니다. 좀 더 상세한 제 이력서 혹은 Private 프로젝트 접근 권한을 원하신다면 메일주세요. 😎

Star
Useful Links