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-except
및 try-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 전용