다음을 통해 공유


Structured Exception Handling (C/C++)

SEH(구조화된 예외 처리)는 하드웨어 오류와 같은 특정 예외 코드 상황을 적절하게 처리하기 위한 C 및 C++에 대한 Microsoft 확장입니다. Windows 및 Microsoft C++는 SEH를 지원하지만 C++ 코드에서는 ISO 표준 C++ 예외 처리를 사용하는 것이 좋습니다. 코드를 더욱 이식 가능하고 유연하게 만듭니다. 그러나 기존 코드를 유지하거나 특정 종류의 프로그램에 대해서는 SEH를 사용해야 할 수도 있습니다.

Microsoft 전용:

문법

try-except-statement:\
__try compound-statement __except ( filter-expression ) compound-statement

try-finally-statement:\
__try compound-statement __finally compound-statement

설명

SEH를 사용하면 실행이 예기치 않게 종료되는 경우 메모리 블록 및 파일과 같은 리소스가 올바르게 해제되도록 보장할 수 있습니다. goto 문을 사용하지 않는 간결한 구조의 코드나 반환 코드의 정교한 테스트를 사용하여 메모리 부족 등의 특정 문제를 처리할 수도 있습니다.

이 문서에 언급된 try-excepttry-finally 문은 C 및 C++ 언어에 대한 Microsoft 확장입니다. 둘 다 애플리케이션이 그렇지 않을 경우 실행을 종료하는 이벤트 후에 프로그램을 제어할 수 있도록 하여 SEH를 지원합니다. SEH는 C++ 소스 파일에서 작동하지만 C++용으로 특별히 설계된 것은 아닙니다. /EHa 또는 /EHsc 옵션을 사용하여 컴파일하는 C++ 프로그램에서 SEH를 사용하는 경우 로컬 개체에 대한 소멸자가 호출되지만 다른 실행 동작은 예상과 다를 수 있습니다. 설명을 보려면 이 문서의 뒷부분에 있는 예를 참조하세요. 대부분의 경우 SEH 대신 ISO 표준 C++ 예외 처리를 사용하는 것이 좋습니다. C++ 예외 처리를 사용하면 코드 포팅 가능성이 향상되며 모든 형식의 예외를 처리할 수 있습니다.

SEH를 사용하는 C 코드가 있는 경우 이를 C++ 예외 처리를 사용하는 C++ 코드와 혼합할 수 있습니다. 자세한 내용은 C++에서 구조화된 예외 처리를 참조하세요.

SEH 메커니즘에는 다음 두 가지가 있습니다.

  • 예외 처리기 또는 __except 블록은 filter-expression 값을 기반으로 예외에 응답하거나 예외를 해제할 수 있습니다. 자세한 내용은 try-except을 참조하세요.

  • 종료 처리기 또는 __finally 블록은 예외로 인해 종료가 발생하는지 여부에 관계없이 항상 호출됩니다. 자세한 내용은 try-finally을 참조하세요.

이러한 두 종류의 처리기는 별개이지만 스택 해제라는 프로세스를 통해 긴밀하게 연결됩니다. 구조화된 예외가 발생하면 Windows는 현재 활성화된 가장 최근에 설치된 예외 처리기를 찾습니다. 처리기는 다음 세 가지 작업 중 하나를 수행할 수 있습니다.

  • 예외를 인식하지 못하고 다른 처리기에 제어를 전달합니다(EXCEPTION_CONTINUE_SEARCH).

  • 예외를 인식하지만 해제합니다(EXCEPTION_CONTINUE_EXECUTION).

  • 예외를 인식하고 처리합니다(EXCEPTION_EXECUTE_HANDLER).

예외가 발생할 때 실행 중이던 함수에 예외를 인식하는 예외 처리기가 없을 수 있습니다. 스택에서 훨씬 더 높은 함수에 있을 수 있습니다. 현재 실행 중인 함수 및 스택 프레임의 다른 모든 함수가 종료됩니다. 이 프로세스 동안 스택은 해제됩니다. 즉, 종료된 함수의 로컬 비정적 변수가 스택에서 지워집니다.

스택을 해제할 때 운영 체제는 각 함수에 대해 작성된 종료 처리기를 모두 호출합니다. 종료 처리기를 사용하면 그렇지 않을 경우 비정상적인 종료 때문에 열려 있을 리소스를 정리합니다. 중요한 섹션을 입력한 경우 종료 처리기에서 끝낼 수 있습니다. 프로그램이 종료되면 임시 파일 닫기 및 제거와 같은 다른 관리 작업을 수행할 수 있습니다.

다음 단계

예시

앞에서 설명한 것처럼 C++ 프로그램에서 SEH를 사용하고 /EHa 또는 /EHsc 옵션을 사용하여 컴파일하면 로컬 개체에 대한 소멸자가 호출됩니다. 그러나 C++ 예외도 사용하는 경우 실행 중의 동작은 예상과 다를 수 있습니다. 이 예에서는 이러한 동작 차이를 보여 줍니다.

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

class TestClass
{
public:
    ~TestClass()
    {
        printf("Destroying TestClass!\n");
    }
};

__declspec(noinline) void TestCPPEX()
{
#ifdef CPPEX
    printf("Throwing C++ exception\n");
    throw std::exception("");
#else
    printf("Triggering SEH exception\n");
    volatile int *pInt = 0x00000000;
    *pInt = 20;
#endif
}

__declspec(noinline) void TestExceptions()
{
    TestClass d;
    TestCPPEX();
}

int main()
{
    __try
    {
        TestExceptions();
    }
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
        printf("Executing SEH __except block\n");
    }

    return 0;
}

/EHsc를 사용하여 이 코드를 컴파일했지만 로컬 테스트 제어 매크로 CPPEX가 정의되지 않은 경우 TestClass 소멸자는 실행되지 않습니다. 출력은 다음과 같습니다.

Triggering SEH exception
Executing SEH __except block

/EHsc를 사용하여 코드를 컴파일하고 C++ 예외가 throw되도록 CPPEX/DCPPEX를 사용하여 정의된 경우 TestClass 소멸자가 실행되고 출력은 다음과 같습니다.

Throwing C++ exception
Destroying TestClass!
Executing SEH __except block

/EHa를 사용하여 코드를 컴파일하는 경우 표준 C++ throw 식을 사용하여 예외가 throw되든, SEH를 사용하여 throw되든 TestClass 소멸자가 실행됩니다. 즉, CPPEX가 정의되었는지 여부를 나타냅니다. 출력은 다음과 같습니다.

Throwing C++ exception
Destroying TestClass!
Executing SEH __except block

자세한 내용은 /EH(예외 처리 모델)을 참조하세요.

END Microsoft 전용

참고 항목

예외 처리
키워드
<exception>
오류 및 예외 처리
구조화된 예외 처리(Windows)