VS2008使用SEH启用C ++异常 [英] VS2008 Enable C++ Exception with SEH

查看:183
本文介绍了VS2008使用SEH启用C ++异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不希望我的程序崩溃,所以我启用了SEH的C ++异常。所以,如果有一些错误,即NULL指针访问发生,我的程序可以捕获它与catch(...)。



我想知道:
1.使用SEH启用C ++异常有什么缺点吗?
2.当catch(...)被捕获时,我如何知道异常详细信息?

解决方案


  1. 据我所知,没有性能缺陷,因为我很确定C ++异常是通过SEH实现的。所有您正在做的是使扩展程序也能够获得操作系统级异常。通常情况下,您通常使用 __尝试和 code> __除了以捕获SEH异常; 此处有更多信息。注意这里的缺点是:异常捕获这种方式不运行析构函数。但是,您可以使用函数 _set_se_translator 将SEH异常转换为C ++异常。


这是我的一个项目,这样做(在MSVC 2010中使用Boost和C ++ 0x):

  bool ignore_exception(unsigned pCode)
{
const unsigned ignoreList [] = {EXCEPTION_BREAKPOINT,
EXCEPTION_FLT_DENORMAL_OPERAND,EXCEPTION_FLT_DIVIDE_BY_ZERO,
EXCEPTION_FLT_INEXACT_RESULT,EXCEPTION_FLT_OVERFLOW,EXCEPTION_FLT_UNDERFLOW,
EXCEPTION_INT_OVERFLOW,EXCEPTION_SINGLE_STEP};

auto result = std :: search_n(std :: begin(ignoreList),std :: end(ignoreList),
1,pCode);
return result!= std :: end(ignoreList);


std :: string code_string(unsigned pCode)
{
switch(pCode)
{
case EXCEPTION_ACCESS_VIOLATION:
返回访问冲突;
case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
returnOut of array bounds;
case EXCEPTION_BREAKPOINT:
returnBreakpoint;
case EXCEPTION_DATATYPE_MISALIGNMENT:
returnMisaligned data;
case EXCEPTION_FLT_DENORMAL_OPERAND:
return非规范化浮点值;
case EXCEPTION_FLT_DIVIDE_BY_ZERO:
returnFloating-point divide-by-zero;
case EXCEPTION_FLT_INEXACT_RESULT:
return不精确的浮点值;
case EXCEPTION_FLT_INVALID_OPERATION:
return无效的浮点运算;
case EXCEPTION_FLT_OVERFLOW:
return浮点溢出;
case EXCEPTION_FLT_STACK_CHECK:
return浮点堆栈溢出;
case EXCEPTION_FLT_UNDERFLOW:
returnFloating-point underflow;
case EXCEPTION_GUARD_PAGE:
returnPage-guard access;
case EXCEPTION_ILLEGAL_INSTRUCTION:
return非法指令;
case EXCEPTION_IN_PAGE_ERROR:
returnInvalid page access;
case EXCEPTION_INT_DIVIDE_BY_ZERO:
returnInteger divide by-zero;
case EXCEPTION_INT_OVERFLOW:
returnInteger overflow;
case EXCEPTION_INVALID_DISPOSITION:
returnInvalid exception dispatcher;
case EXCEPTION_INVALID_HANDLE:
returnInvalid handle;
case EXCEPTION_NONCONTINUABLE_EXCEPTION:
return不可持续的异常;
case EXCEPTION_PRIV_INSTRUCTION:
returnInvalid instruction;
case EXCEPTION_SINGLE_STEP:
returnSingle instruction step;
case EXCEPTION_STACK_OVERFLOW:
returnStack overflow;
默认值:
返回未知异常;
}
}

void stack_fail_thread()
{
std :: cerr<< 未处理的例外:\\\

<< code_string(EXCEPTION_STACK_OVERFLOW)<< \\\
;
std :: cerr<<< 终止。 <<的std :: ENDL;

//可以打印失败的
//线程的堆栈转储,看看发生了什么问题,等等...

std :: exit(EXIT_FAILURE) ;
}

void exception_translator(unsigned pCode,_EXCEPTION_POINTERS *)
{
//如果是堆栈溢出,最小化函数调用
if(pCode == EXCEPTION_STACK_OVERFLOW)
{
//在另一个线程中执行一些额外的处理,
//因为此线程的堆栈已经消失
boost :: thread t(stack_fail_thread);
t.join(); //永远不会退出
}
else if(!ignore_exception(pCode))
{
//可以向异常消息添加堆栈转储
//因为这些往往很严重,等等...
BOOST_THROW_EXCEPTION(std :: runtime_error(code_string(pCode)));
}
}

void hook_signals()
{
_set_se_translator(exception_translator);
}

我删除了几件事情,但你得到了这个想法。您可以通过这种方式提取所有相同的信息。


I don't want my program to crash, so i enabled C++ Exception with SEH. So that, if there's some errors i.e. NULL pointer access happens, my program can catch it with catch(...).

I want to known: 1. Is there any drawback of enable C++ exception with SEH? 2. How can i know exception details when it is catched by catch(...)?

解决方案

  1. As far as I know, there are no performance drawbacks, because I'm pretty sure C++ exceptions are implemented via SEH anyway. All you're doing is enabling the extension to get OS-level exceptions as well. However, there is one major drawback, touched on in two.

  2. You normally use __try and __except to catch SEH exceptions; more information here. Note this is where the drawback is: exceptions caught this way do not run destructors. However, what you can do is use the function _set_se_translator to translate SEH exceptions into C++ exceptions.

Here's something from one of my projects that does this (uses Boost and C++0x in MSVC 2010):

bool ignore_exception(unsigned pCode)
{
    const unsigned ignoreList[] = {EXCEPTION_BREAKPOINT,
        EXCEPTION_FLT_DENORMAL_OPERAND, EXCEPTION_FLT_DIVIDE_BY_ZERO,
        EXCEPTION_FLT_INEXACT_RESULT, EXCEPTION_FLT_OVERFLOW, EXCEPTION_FLT_UNDERFLOW,
        EXCEPTION_INT_OVERFLOW, EXCEPTION_SINGLE_STEP};

    auto result = std::search_n(std::begin(ignoreList), std::end(ignoreList),
                    1, pCode);
    return result != std::end(ignoreList);              
}

std::string code_string(unsigned pCode)
{
    switch (pCode)
    {
    case EXCEPTION_ACCESS_VIOLATION:
        return "Access violation";
    case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
        return "Out of array bounds";
    case EXCEPTION_BREAKPOINT:
        return "Breakpoint";
    case EXCEPTION_DATATYPE_MISALIGNMENT:
        return "Misaligned data";
    case EXCEPTION_FLT_DENORMAL_OPERAND:
        return "Denormalized floating-point value";
    case EXCEPTION_FLT_DIVIDE_BY_ZERO:
        return "Floating-point divide-by-zero";
    case EXCEPTION_FLT_INEXACT_RESULT:
        return "Inexact floating-point value";
    case EXCEPTION_FLT_INVALID_OPERATION:
        return "Invalid floating-point operation";
    case EXCEPTION_FLT_OVERFLOW:
        return "Floating-point overflow";
    case EXCEPTION_FLT_STACK_CHECK:
        return "Floating-point stack overflow";
    case EXCEPTION_FLT_UNDERFLOW:
        return "Floating-point underflow";
    case EXCEPTION_GUARD_PAGE:
        return "Page-guard access";
    case EXCEPTION_ILLEGAL_INSTRUCTION:
        return "Illegal instruction";
    case EXCEPTION_IN_PAGE_ERROR:
        return "Invalid page access";
    case EXCEPTION_INT_DIVIDE_BY_ZERO:
        return "Integer divide-by-zero";
    case EXCEPTION_INT_OVERFLOW:
        return "Integer overflow";
    case EXCEPTION_INVALID_DISPOSITION:
        return "Invalid exception dispatcher";
    case EXCEPTION_INVALID_HANDLE:
        return "Invalid handle";
    case EXCEPTION_NONCONTINUABLE_EXCEPTION:
        return "Non-continuable exception";
    case EXCEPTION_PRIV_INSTRUCTION:
        return "Invalid instruction";
    case EXCEPTION_SINGLE_STEP:
        return "Single instruction step";
    case EXCEPTION_STACK_OVERFLOW:
        return "Stack overflow";
    default:
        return "Unknown exception";
    }
}

void stack_fail_thread()
{
    std::cerr << "Unhandled exception:\n"
                << code_string(EXCEPTION_STACK_OVERFLOW) << '\n';
    std::cerr << "Terminating." << std::endl;

    // can print a stack dump of the failed
    // thread to see what went wrong, etc...

    std::exit(EXIT_FAILURE);
}

void exception_translator(unsigned pCode, _EXCEPTION_POINTERS*)
{
    // minimize function calls if it's a stack overflow
    if (pCode == EXCEPTION_STACK_OVERFLOW)
    {
        // do some additional processing in another thread,
        // because the stack of this thread is gone
        boost::thread t(stack_fail_thread);
        t.join(); // will never exit
    }
    else if (!ignore_exception(pCode))               
    {
        // can add a stack dump to the exception message,
        // since these tend to be pretty severe, etc...
        BOOST_THROW_EXCEPTION(std::runtime_error(code_string(pCode)));
    }
}

void hook_signals()
{
    _set_se_translator(exception_translator);
}

I stripped several things out, but you get the idea. You can extract all the same information this way.

这篇关于VS2008使用SEH启用C ++异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆