C++에서 구조적 예외 처리
C SEH(구조적 예외 처리)와 C++ 예외 처리의 주요 차이점은 C++ 예외 처리 모델이 형식을 처리하는 반면 C 구조적 예외 처리 모델은 한 형식의 예외를 처리한다는 점입니다. 특히 , unsigned int
. 즉, C 예외는 부호 없는 정수 값으로 식별되는 반면 C++ 예외는 데이터 형식으로 식별됩니다. C에서 구조적 예외가 발생하면 가능한 각 처리기는 C 예외 컨텍스트를 검사하고 예외를 수락할지, 다른 처리기에 전달할지 또는 무시할지를 결정하는 필터를 실행합니다. C++에서 예외가 발생하는 경우 예외는 어떤 형식이든 가능합니다.
두 번째 차이점은 예외가 일반적인 제어 흐름에 보조로 발생하기 때문에 C 구조적 예외 처리 모델을 비동기라고 한다는 것입니다. C++ 예외 처리 메커니즘은 완전히 동기적입니다. 즉, 예외가 throw된 경우에만 발생합니다.
/EHs 또는 /EHsc 컴파일러 옵션을 사용하는 경우 C++ 예외 처리기가 구조적 예외를 처리하지 않습니다. 이러한 예외는 구조적 예외 처리기 또는 __finally
구조적 종료 처리기에서만 __except
처리됩니다. 자세한 내용은 구조적 예외 처리(C/C++)를 참조하세요.
/EHa 컴파일러 옵션에서 C++ 프로그램에서 C 예외가 발생하는 경우 연결된 필터를 사용하는 구조적 예외 처리기 또는 예외 컨텍스트에 동적으로 더 가까운 C++ catch
처리기를 통해 처리할 수 있습니다. 예를 들어 이 샘플 C++ 프로그램은 C++ try
컨텍스트 내에서 C 예외를 발생합니다.
예제 - C++ catch 블록에서 C 예외 catch
// exceptions_Exception_Handling_Differences.cpp
// compile with: /EHa
#include <iostream>
using namespace std;
void SEHFunc( void );
int main() {
try {
SEHFunc();
}
catch( ... ) {
cout << "Caught a C exception."<< endl;
}
}
void SEHFunc() {
__try {
int x, y = 0;
x = 5 / y;
}
__finally {
cout << "In finally." << endl;
}
}
In finally.
Caught a C exception.
C 예외 래퍼 클래스
위와 같은 간단한 예제에서 C 예외는 줄임표(...) catch
처리기에서만 catch할 수 있습니다. 예외의 형식이나 특성에 대한 정보가 처리기로 전달되지 않습니다. 이 메서드는 작동하지만 경우에 따라 각 C 예외가 특정 클래스와 연결되도록 두 예외 처리 모델 간에 변환을 정의할 수 있습니다. 하나를 변환하려면 C 예외 "래퍼" 클래스를 정의할 수 있습니다. 이 클래스는 특정 클래스 형식을 C 예외로 특성화하기 위해 사용하거나 파생할 수 있습니다. 이렇게 하면 각 C 예외는 단일 처리기에서 모든 예외가 아닌 특정 C++ catch
처리기에 의해 개별적으로 처리될 수 있습니다.
래퍼 클래스에는 예외 값을 결정하는 멤버 함수로 구성되며 C 예외 모델에서 제공하는 확장된 예외 컨텍스트 정보에 액세스하는 인터페이스가 있을 수 있습니다. 기본 생성자 및 인수를 허용하는 unsigned int
생성자(기본 C 예외 표현을 제공하기 위해) 및 비트 복사 생성자를 정의할 수도 있습니다. C 예외 래퍼 클래스의 가능한 구현은 다음과 같습니다.
// exceptions_Exception_Handling_Differences2.cpp
// compile with: /c
class SE_Exception {
private:
SE_Exception() {}
SE_Exception( SE_Exception& ) {}
unsigned int nSE;
public:
SE_Exception( unsigned int n ) : nSE( n ) {}
~SE_Exception() {}
unsigned int getSeNumber() {
return nSE;
}
};
이 클래스를 사용하려면 C 예외가 throw 될 때마다 내부 예외 처리 메커니즘에 의해 호출되는 사용자 지정 C 예외 변환 함수를 설치합니다. 번역 함수 내에서 적절한 일치하는 C++ catch
처리기에서 SE_Exception
catch할 수 있는 형식화된 예외(형식 SE_Exception
또는 파생된 클래스 형식)를 throw할 수 있습니다. 대신 변환 함수는 예외를 처리하지 않았음을 나타내는 반환할 수 있습니다. 변환 함수 자체가 C 예외 를 발생시킬 경우 종료 가 호출됩니다.
사용자 지정 번역 함수를 지정하려면 번역 함수의 이름을 사용하여 _set_se_translator 함수를 단일 인수로 호출합니다. 작성하는 변환 함수는 블록이 있는 스택의 각 함수 호출에 대해 한 번 호출됩니다 try
. 기본 변환 함수는 없습니다. _set_se_translator 호출하여 지정하지 않으면 줄임표 catch
처리기에서만 C 예외를 catch할 수 있습니다.
예제 - 사용자 지정 번역 함수 사용
예를 들어 다음 코드에서는 사용자 지정 변환 함수를 설치한 후 SE_Exception
클래스로 래핑된 C 예외를 발생시킵니다.
// exceptions_Exception_Handling_Differences3.cpp
// compile with: /EHa
#include <stdio.h>
#include <eh.h>
#include <windows.h>
class SE_Exception {
private:
SE_Exception() {}
unsigned int nSE;
public:
SE_Exception( SE_Exception& e) : nSE(e.nSE) {}
SE_Exception(unsigned int n) : nSE(n) {}
~SE_Exception() {}
unsigned int getSeNumber() { return nSE; }
};
void SEFunc() {
__try {
int x, y = 0;
x = 5 / y;
}
__finally {
printf_s( "In finally\n" );
}
}
void trans_func( unsigned int u, _EXCEPTION_POINTERS* pExp ) {
printf_s( "In trans_func.\n" );
throw SE_Exception( u );
}
int main() {
_set_se_translator( trans_func );
try {
SEFunc();
}
catch( SE_Exception e ) {
printf_s( "Caught a __try exception with SE_Exception.\n" );
printf_s( "nSE = 0x%x\n", e.getSeNumber() );
}
}
In trans_func.
In finally
Caught a __try exception with SE_Exception.
nSE = 0xc0000094