Поделиться через


_set_se_translator

Задайте функцию обратного вызова для каждого потока, чтобы преобразовать исключения Win32 (структурированные исключения C) в типизированные исключения C++.

Синтаксис

_se_translator_function _set_se_translator(
    _se_translator_function seTransFunction
);

Параметры

seTransFunction
Указатель на функцию-преобразователь структурированного исключения языка С, создаваемую пользователем.

Возвращаемое значение

Возвращает указатель на предыдущую функцию-преобразователь, зарегистрированную с помощью _set_se_translator, чтобы предыдущую функцию можно было впоследствии восстановить. Если предыдущая функция не задана, возвращаемое значение может использоваться для восстановления поведения по умолчанию; это значение может быть равно nullptr.

Замечания

Функция _set_se_translator предоставляет способ обработки исключений Win32 (структурированных исключений языка C) как типизированных исключений C++. Чтобы разрешить обработчику catch языка С++ обрабатывать каждое исключение языка С, сначала следует определить класс-оболочку исключения языка С, который (или производный от него класс) может использоваться в качестве атрибута специального типа класса для исключения языка С. Чтобы использовать этот класс, требуется установить пользовательскую функцию преобразования исключений языка C, которая вызывается внутренним механизмом обработки исключением при каждом возникновении исключения языка C. Внутри функции-преобразователя можно вызывать любое типизированное исключение, которое может перехватываться соответствующим блоком catch языка С++.

При использовании _set_se_translatorнеобходимо использовать /EHa этот параметр.

Чтобы указать пользовательскую функцию перевода, вызовите _set_se_translator имя функции перевода в качестве аргумента. Созданная функция-преобразователь вызывается по одному разу на каждый вызов функции для стека, имеющего блоки try. Функция переводчика по умолчанию отсутствует.

Функция-преобразователь не должна делать ничего другого, кроме вызова типизированного исключения языка С++. Если это делает что-либо в дополнение к вызову (например, запись в файл журнала), программа может не вести себя должным образом, так как количество вызовов функции переводчика зависит от платформы.

В многопоточной среде функции-преобразователи поддерживаются отдельно для каждого потока. Каждый новый поток требует установки собственной функции-преобразователя. Таким образом, каждый поток владеет собственной обработкой преобразования. _set_se_translator относится к одной библиотеке DLL- в другом потоке, может установить другую функцию перевода.

Функция, которую вы записываете seTransFunction , должна быть скомпилированной в собственном коде (не компилируется с /clr). В качестве аргументов она должна принимать целое число без знака и указатель на структуру Win32 _EXCEPTION_POINTERS. Аргументы являются возвращаемыми значениями вызовов функций GetExceptionCode и GetExceptionInformation API Win32, соответственно.

typedef void (__cdecl *_se_translator_function)(unsigned int, struct _EXCEPTION_POINTERS* );

Для функции _set_se_translator динамическое связывание с CRT может приводить к определенным последствиям; другая библиотека DLL в процессе может вызвать функцию _set_se_translator и заменить обработчик собственным.

При использовании _set_se_translator управляемого кода (скомпилированного с /clrпомощью кода) или смешанного машинного и управляемого кода переводчик влияет на исключения, созданные только в машинном коде. Все управляемые исключения, созданные в управляемом коде (например, при создании System::Exception) не направляются через функцию переводчика. Исключения, вызванные в управляемом коде с помощью функции RaiseException Win32 или вызванные системным исключением, таким как исключение деления на ноль, маршрутизируются через преобразователь.

Требования

Маршрут Обязательный заголовок
_set_se_translator <eh.h>

Дополнительные сведения о совместимости см. в разделе Совместимость.

Пример: ошибка перехвата __try исключения

В этом примере выполняется оболочка вызовов для задания структурированного переводчика исключений RAII и восстановления старого в классе Scoped_SE_Translator. Этот класс позволяет ввести переводчик с определенной областью в виде одного объявления. Деструктор класса восстанавливает исходный переводчик, когда элемент управления покидает область.

// 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код. Если структурированное исключение создается в управляемом коде, который должен быть сопоставлен, код, создающий и обрабатывающий исключение, должен быть помечен #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