다음을 통해 공유


_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 GetExceptionCodeGetExceptionInformation 함수에 대한 호출의 반환 값입니다.

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

참고 항목

예외 처리 루틴
set_terminate
set_unexpected
terminate
unexpected