_set_se_translator
스레드별 콜백 함수를 설정하여 Win32 예외(C 구조적 예외)를 C++ 형식의 예외로 변환합니다.
구문
_se_translator_function _set_se_translator(
_se_translator_function seTransFunction
);
매개 변수
seTransFunction
작성하는 C 구조적 예외 변환기 함수에 대한 포인터입니다.
반환 값
이전 함수를 나중에 복원할 수 있도록 _set_se_translator
에서 등록한 이전 변환기 함수에 대한 포인터를 반환합니다. 이전 함수가 설정되어 있지 않은 경우 반환 값을 사용하여 기본 동작을 복원할 수 있습니다. 이 값은 nullptr
일 수 있습니다.
설명
_set_se_translator
함수는 Win32 예외(C 구조적 예외)를 C++ 형식 예외로 처리하는 방법을 제공합니다. 각 C 예외가 C++ catch
처리기에 의해 처리되도록 허용하려면 먼저 특정 클래스 형식의 특성을 C 예외로 지정하도록 사용 또는 파생될 수 있는 C 예외 래퍼 클래스를 정의합니다. 이 클래스를 사용하려면 C 예외가 발생할 때마다 내부 예외 처리 메커니즘을 통해 호출되는 사용자 지정 C 예외 변환기 함수를 설치합니다. 변환기 함수 내에서 일치하는 C++ catch
처리기에 의해 catch될 수 있는 모든 형식의 예외를 throw할 수 있습니다.
를 사용할 때는 이 /EHa
옵션을 사용해야 _set_se_translator
합니다.
사용자 지정 번역 함수를 지정하려면 번역 함수의 이름을 인수로 사용하여 호출 _set_se_translator
합니다. 사용자가 작성한 변환기 함수는 try
블록이 있는 스택의 각 함수 호출에 대해 한 번씩 호출됩니다. 기본 Translator 함수는 없습니다.
변환기 함수는 C++ 형식의 예외만 발생시켜야 합니다. throw(예: 로그 파일에 쓰기 등) 외에 아무 작업도 수행하는 경우 Translator 함수의 호출 수는 플랫폼에 따라 달라지므로 프로그램이 예상대로 작동하지 않을 수 있습니다.
다중 스레드 환경에서 변환기 함수는 각 스레드에 대해 개별적으로 유지 관리됩니다. 각 새 스레드는 자체 변환기 함수를 설치해야 합니다. 따라서 각 스레드는 자체 변환 처리를 담당합니다. _set_se_translator
는 한 스레드에만 해당합니다. 다른 DLL은 다른 변환 함수를 설치할 수 있습니다.
작성하는 함수는 seTransFunction
네이티브 컴파일 함수여야 합니다(컴파일되지 /clr
않음). 이 함수는 부호 없는 정수 및 Win32 _EXCEPTION_POINTERS
구조체에 대한 포인터를 인수로 사용해야 합니다. 인수는 각각 Win32 API GetExceptionCode
및 GetExceptionInformation
함수에 대한 호출의 반환 값입니다.
typedef void (__cdecl *_se_translator_function)(unsigned int, struct _EXCEPTION_POINTERS* );
_set_se_translator
의 경우 동적으로 CRT에 연결할 때 의미하는 사항이 있습니다. 즉, 프로세스의 다른 DLL이 _set_se_translator
를 호출하고 처리기를 자체 처리기로 대체할 수 있습니다.
관리 코드(코드로 /clr
컴파일됨) 또는 혼합 네이티브 및 관리 코드에서 사용하는 _set_se_translator
경우 변환기에서는 네이티브 코드에서만 생성된 예외에만 영향을 줍니다. 관리 코드에서 생성된 관리되는 예외(예: 발생 System::Exception
시)는 Translator 함수를 통해 라우팅되지 않습니다. Win32 함수 RaiseException
을 사용하여 관리 코드에서 발생하는 예외 또는 0으로 나누기 예외와 같은 시스템 예외에 의해 발생하는 예외가 변환기를 통해 라우팅됩니다.
요구 사항
루틴에서 반환된 값 | 필수 헤더 |
---|---|
_set_se_translator |
<eh.h> |
호환성에 대한 자세한 내용은 호환성을 참조하세요.
예제: Catch __try
예외 오류
이 샘플에서는 구조적 예외 변환기를 설정하고 클래스Scoped_SE_Translator
의 이전 변환기를 복원하기 위한 호출을 RAII
래핑합니다. 이 클래스를 사용하면 범위별 번역기를 단일 선언으로 도입할 수 있습니다. 컨트롤이 범위를 벗어나면 클래스 소멸자가 원래 변환기를 복원합니다.
// crt_settrans.cpp
// compile with: cl /W4 /EHa crt_settrans.cpp
#include <stdio.h>
#include <windows.h>
#include <eh.h>
#include <exception>
class SE_Exception : public std::exception
{
private:
const unsigned int nSE;
public:
SE_Exception() noexcept : SE_Exception{ 0 } {}
SE_Exception( unsigned int n ) noexcept : nSE{ n } {}
unsigned int getSeNumber() const noexcept { return nSE; }
};
class Scoped_SE_Translator
{
private:
const _se_translator_function old_SE_translator;
public:
Scoped_SE_Translator( _se_translator_function new_SE_translator ) noexcept
: old_SE_translator{ _set_se_translator( new_SE_translator ) } {}
~Scoped_SE_Translator() noexcept { _set_se_translator( old_SE_translator ); }
};
void SEFunc()
{
__try
{
printf( "In __try, about to force exception\n" );
int x = 5;
int y = 0;
int *p = &y;
*p = x / *p;
}
__finally
{
printf( "In __finally\n" );
}
}
void trans_func( unsigned int u, EXCEPTION_POINTERS* )
{
throw SE_Exception( u );
}
int main()
{
Scoped_SE_Translator scoped_se_translator{ trans_func };
try
{
SEFunc();
}
catch( const SE_Exception& e )
{
printf( "Caught a __try exception, error %8.8x.\n", e.getSeNumber() );
}
}
In __try, about to force exception
In __finally
Caught a __try exception, error c0000094.
예: Catch SE_Exception
오류
제공된 _set_se_translator
기능은 관리 코드에서 사용할 수 없지만 네이티브 코드가 사용으로 표시되는 한 네이티브 코드가 스위치 아래 /clr
의 컴파일에 있더라도 네이티브 코드에서 이 매핑을 사용할 #pragma unmanaged
수 있습니다. 매핑할 관리 코드에서 구조적 예외가 throw되는 경우 예외를 생성하고 처리하는 코드는 표시 #pragma unmanaged
되어야 합니다. 다음 코드에서는 가능한 사용법을 보여 줍니다. 자세한 내용은 Pragma 지시문 및 키워드를 __pragma
_Pragma
참조하세요.
// crt_set_se_translator_clr.cpp
// compile with: cl /W4 /clr crt_set_se_translator_clr.cpp
#include <windows.h>
#include <eh.h>
#include <stdio.h>
#include <exception>
int thrower_func( int i ) {
int y = 0;
int *p = &y;
*p = i / *p;
return 0;
}
class SE_Exception : public std::exception
{
private:
const unsigned int nSE;
public:
SE_Exception() noexcept : SE_Exception{ 0 } {}
SE_Exception( unsigned int n ) noexcept : nSE{ n } {}
unsigned int getSeNumber() const noexcept { return nSE; }
};
class Scoped_SE_Translator
{
private:
const _se_translator_function old_SE_translator;
public:
Scoped_SE_Translator( _se_translator_function new_SE_translator ) noexcept
: old_SE_translator{ _set_se_translator( new_SE_translator ) } {}
~Scoped_SE_Translator() noexcept { _set_se_translator( old_SE_translator ); }
};
#pragma unmanaged
void my_trans_func( unsigned int u, PEXCEPTION_POINTERS )
{
throw SE_Exception( u );
}
void DoTest()
{
try
{
thrower_func( 10 );
}
catch( const SE_Exception& e )
{
printf( "Caught SE_Exception, error %8.8x\n", e.getSeNumber() );
}
catch(...)
{
printf( "Caught unexpected SEH exception.\n" );
}
}
#pragma managed
int main() {
Scoped_SE_Translator scoped_se_translator{ my_trans_func };
DoTest();
}
Caught SE_Exception, error c0000094