다음을 통해 공유


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_Exceptioncatch할 수 있는 형식화된 예외(형식 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

참고 항목

C(구조적) 및 C++ 예외 혼합