如何处理所有错误,包括内部C库错误,统一 [英] How to handle all errors, including internal C library errors, uniformly

查看:417
本文介绍了如何处理所有错误,包括内部C库错误,统一的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



正如所讨论的那样这里,使用 _set_se_translator 捕获零分错误。



但是它不能捕获,例如,C运行时库错误 -1073740777(0xc0000417),这可能是由 printf ,它们不应该有百分号。 (这只是一个例子,当然我们应该检查这样的字符串)。要处理这些,需要 _set_invalid_parameter_handler



还有其他十个这样的处理程序列在



此外,这将捕获未捕获的C ++异常: SetUnhandledExceptionFilter 。因此,它可以与 __ set__ ... 功能一起使用。 (在MSVC 2008中有关使用它的文章。)



我想捕获任何和所有错误,以便我可以处理它们(通过记录,抛出现代C ++标准异常并返回应用程序特定的错误代码)。有一个单一的处理程序捕获一切吗?



另请参阅 StackOverflow



我正在使用Visual Studio 2008。

解决方案

没有通用处理程序。您需要安装每个。我使用过这样的东西:

  ///////////////// ////////////////////////////////////////////////// ////// 
template< class K,class V>
class MapInitializer
{
std :: map< K,V>米;
public:
运算符std :: map< K,V>()const
{
return m;
}

MapInitializer&添加(const K& k,const V& v)
{
m [k] = v;
return * this;
}
};

////////////////////////////////////// /////////////////
struct StructuredException:std :: exception
{
const char * const msg;
StructuredException(const char * const msg_):msg(msg_){}
virtual const char * what()const {return msg; }
};

////////////////////////////////////// /////////////////
class ExceptionHandlerInstaller
{
public:
ExceptionHandlerInstaller()
:m_oldTerminateHandler(std :: set_terminate(TerminateHandler))
,m_oldUnexpectedHandler(std :: set_unexpected(UnexpectedHandler))
,m_oldSEHandler(_set_se_translator(SEHandler))
{}

〜ExceptionHandlerInstaller()
{
std :: set_terminate(m_oldTerminateHandler);
std :: set_unexpected(m_oldUnexpectedHandler);
_set_se_translator(m_oldSEHandler);
}

private:
static void TerminateHandler()
{
TRACE(\\\
\\\
**** terminate handler called! **** \\\
\\\
);
}

static void UnexpectedHandler()
{
TRACE(\\\
\\\
****意外异常处理程序调用!**** \\ \\ n \
}

static void SEHandler(const unsigned code,EXCEPTION_POINTERS *)
{
SEMsgMap :: const_iterator it = m_seMsgMap.find(code);
throw StructuredException(it!= m_seMsgMap.end()
?it-> second
:结构化异常转换为C ++异常);
}

const std :: terminate_handler m_oldTerminateHandler;
const std :: unexpected_handler m_oldUnexpectedHandler;
const _se_translator_function m_oldSEHandler;

typedef std :: map< unsigned,const char *> SEMsgMap;
static const SEMsgMap m_seMsgMap;
};

////////////////////////////////////// /////////////////
//从MS帮助文件复制的结构化异常的消息图
//////////////////////////////////////////// ///////////////
const ExceptionHandlerInstaller :: SEMsgMap ExceptionHandlerInstaller :: m_seMsgMap
= MapInitializer< ExceptionHandlerInstaller :: SEMsgMap :: key_type,
ExceptionHandlerInstaller :: SEMsgMap :: mapped_type>()
.Add(EXCEPTION_ACCESS_VIOLATION,该线程尝试读取或写入其无权访问的虚拟地址这个值被定义为STATUS_ACCESS_VIOLATION。)
.Add(EXCEPTION_ARRAY_BOUNDS_EXCEEDED,线程尝试访问超出范围的数组元素,底层硬件支持边界检查,该值定义为STATUS_ARRAY_BOUNDS_EXCEEDED。 )
.Add(EXCEPTION_BREAKPOINT,断点是encounte红。该值定义为STATUS_BREAKPOINT。)
.Add(EXCEPTION_DATATYPE_MISALIGNMENT,线程尝试读取或写入在不提供对齐的硬件上未对齐的数据。例如,16位值必须在2字节边界,4字节边界上的32位值等等,此值定义为STATUS_DATATYPE_MISALIGNMENT。)
.Add(EXCEPTION_FLT_DENORMAL_OPERAND,浮点运算中的一个操作数是非正常的。非正常值是太小,不能表示为标准浮点值,该值定义为STATUS_FLOAT_DENORMAL_OPERAND。)
.Add(EXCEPTION_FLT_DIVIDE_BY_ZERO,线程尝试将浮点值除以浮点除数为0(零),此值定义为STATUS_FLOAT_DIVIDE_BY_ZERO。)
.Add(EXCEPTION_FLT_INEXACT_RESULT,浮点运算的结果不能完全按小数表示,该值被定义为STATUS_FLOAT_INEXACT_RESULT。)
.Add(EXCEPTION_FLT_INVALID_OPERATION,不包括在此列表中的浮点数异常。该值定义为STATUS_FLOAT_INVALID_OPERATION。)
.Add(EXCEPTION_FLT_OVERFLOW,浮点运算的指数大于相应类型允许的大小,此值定义为STATUS_FLOAT_OVERFLOW。)
.Add(EXCEPTION_FLT_STACK_CHECK,由于浮点运算,堆栈溢出或下溢,此值定义为STATUS_FLOAT_STACK_CHECK)
.Add(EXCEPTION_FLT_UNDERFLOW,浮点运算的指数小于这个值被定义为STATUS_FLOAT_UNDERFLOW。)
.Add(EXCEPTION_GUARD_PAGE,使用PAGE_GUARD修饰符分配的线程访问的内存,此值定义为STATUS_GUARD_PAGE_VIOLATION。)
。添加(EXCEPTION_ILLEGAL_INSTRUCTION,线程尝试执行无效指令,该值定义为STATUS_ILLEGAL_INSTRUCTION。 )
.Add(EXCEPTION_IN_PAGE_ERROR,线程尝试访问不存在的页面,系统无法加载页面。例如,如果通过网络运行程序时网络连接丢失,则可能会发生此异常。该值定义为STATUS_IN_PAGE_ERROR。)
.Add(EXCEPTION_INT_DIVIDE_BY_ZERO,线程尝试将整数除数为整数除数为0(零),该值定义为STATUS_INTEGER_DIVIDE_BY_ZERO。)
.Add(EXCEPTION_INT_OVERFLOW,整数运算的结果导致结果的最高有效位的进位,该值定义为STATUS_INTEGER_OVERFLOW。)
.Add(EXCEPTION_INVALID_DISPOSITION,异常处理程序返回无效使用高级语言(如C)的程序员不应该遇到此异常,此值定义为STATUS_INVALID_DISPOSITION。)
.Add(EXCEPTION_INVALID_HANDLE,线程使用内核对象的句柄这是无效的(可能是因为它已被关闭)。此值定义为STATUS_INVALID_HANDLE。)
.Add(EXCEPTION_NONCONTINUABLE_EXCEPTION,线程尝试在发生不可持续异常后继续执行。该值定义为STATUS_NONCONTINUABLE_EXCEPTION。)
.Add(EXCEPTION_PRIV_INSTRUCTION,线程尝试执行具有当前计算机模式下不允许的操作的指令,此值定义为STATUS_PRIVILEGED_INSTRUCTION。)
.Add(EXCEPTION_SINGLE_STEP,跟踪陷阱或其他单指令机制发出一条指令执行的信号,该值定义为STATUS_SINGLE_STEP)
.Add(EXCEPTION_STACK_OVERFLOW,线程使用它的堆栈值被定义为STATUS_STACK_OVERFLOW。);

然后在main或app init中,我这样做: / p>

  BOOL CMyApp :: InitInstance()
{
ExceptionHandlerInstaller ehi;
// ..
}

请注意,这将结构化异常转换为常规异常,但处理终止例如,当一个nothrow()函数抛出一个exc时通过简单地打印错误信息。您不希望为所有不同类型的错误使用单个处理程序,这就是为什么他们不提供它。


I wanted to handle all internal errors gracefully, without program termination.

As discussed here, using _set_se_translator catches divide-by-zero errors.

But it does not catch, for example, C runtime library error -1073740777 (0xc0000417), which can be caused by format strings for printf which have the percent sign where they shouldn't. (That is just an example; of course we should check for such strings). To handle these, _set_invalid_parameter_handler is needed.

There are about ten other such handlers listed here.

In addition, this one will catch uncaught C++ exceptions: SetUnhandledExceptionFilter. Thus, it can be used together with the __set__ ... functions. (An article about using it in MSVC 2008.)

I want to catch any and all errors so I can handle them (by logging, throwing a modern C++ standard exception and returning an application-specific error code). Is there a single handler that catches everything?

See also this on StackOverflow.

I am using Visual Studio 2008.

解决方案

There is no universal handler. You need to install each one. I have used something like this:

///////////////////////////////////////////////////////////////////////////
template<class K, class V>
class MapInitializer
{
    std::map<K,V> m;
public:
    operator std::map<K,V>() const 
    { 
        return m; 
    }

    MapInitializer& Add( const K& k, const V& v )
    {
        m[ k ] = v;
        return *this;
    }
};

///////////////////////////////////////////////////////////////////////////
struct StructuredException : std::exception
{
    const char *const msg;
    StructuredException( const char* const msg_ ) : msg( msg_ ) {}
    virtual const char* what() const { return msg; }
};

///////////////////////////////////////////////////////////////////////////
class ExceptionHandlerInstaller
{
public:
    ExceptionHandlerInstaller()
        : m_oldTerminateHandler( std::set_terminate( TerminateHandler ) )
        , m_oldUnexpectedHandler( std::set_unexpected( UnexpectedHandler ) )
        , m_oldSEHandler( _set_se_translator( SEHandler ) )
    {}

    ~ExceptionHandlerInstaller() 
    { 
        std::set_terminate( m_oldTerminateHandler );
        std::set_unexpected( m_oldUnexpectedHandler );
        _set_se_translator( m_oldSEHandler );
    }

private:
    static void TerminateHandler() 
    { 
        TRACE( "\n\n**** terminate handler called! ****\n\n" );
    }

    static void UnexpectedHandler() 
    { 
        TRACE( "\n\n**** unexpected exception handler called! ****\n\n" );
    }

    static void SEHandler( const unsigned code, EXCEPTION_POINTERS* )
    {
        SEMsgMap::const_iterator it = m_seMsgMap.find( code );
        throw StructuredException( it != m_seMsgMap.end() 
            ? it->second 
            : "Structured exception translated to C++ exception." );
    }

    const std::terminate_handler  m_oldTerminateHandler;
    const std::unexpected_handler m_oldUnexpectedHandler;
    const _se_translator_function m_oldSEHandler;

    typedef std::map<unsigned, const char*> SEMsgMap;
    static const SEMsgMap m_seMsgMap;
};

///////////////////////////////////////////////////////////////////////////
// Message map for structured exceptions copied from the MS help file
///////////////////////////////////////////////////////////////////////////
const ExceptionHandlerInstaller::SEMsgMap ExceptionHandlerInstaller::m_seMsgMap 
    = MapInitializer<ExceptionHandlerInstaller::SEMsgMap::key_type, 
                     ExceptionHandlerInstaller::SEMsgMap::mapped_type>()
    .Add( EXCEPTION_ACCESS_VIOLATION,         "The thread attempts to read from or write to a virtual address for which it does not have access. This value is defined as STATUS_ACCESS_VIOLATION." )
    .Add( EXCEPTION_ARRAY_BOUNDS_EXCEEDED,    "The thread attempts to access an array element that is out of bounds, and the underlying hardware supports bounds checking. This value is defined as STATUS_ARRAY_BOUNDS_EXCEEDED." )
    .Add( EXCEPTION_BREAKPOINT,               "A breakpoint is encountered. This value is defined as STATUS_BREAKPOINT." )
    .Add( EXCEPTION_DATATYPE_MISALIGNMENT,    "The thread attempts to read or write data that is misaligned on hardware that does not provide alignment. For example, 16-bit values must be aligned on 2-byte boundaries, 32-bit values on 4-byte boundaries, and so on. This value is defined as STATUS_DATATYPE_MISALIGNMENT." )
    .Add( EXCEPTION_FLT_DENORMAL_OPERAND,     "One of the operands in a floating point operation is denormal. A denormal value is one that is too small to represent as a standard floating point value. This value is defined as STATUS_FLOAT_DENORMAL_OPERAND." )
    .Add( EXCEPTION_FLT_DIVIDE_BY_ZERO,       "The thread attempts to divide a floating point value by a floating point divisor of 0 (zero). This value is defined as STATUS_FLOAT_DIVIDE_BY_ZERO." )
    .Add( EXCEPTION_FLT_INEXACT_RESULT,       "The result of a floating point operation cannot be represented exactly as a decimal fraction. This value is defined as STATUS_FLOAT_INEXACT_RESULT." )
    .Add( EXCEPTION_FLT_INVALID_OPERATION,    "A floatin point exception that is not included in this list. This value is defined as STATUS_FLOAT_INVALID_OPERATION." )
    .Add( EXCEPTION_FLT_OVERFLOW,             "The exponent of a floating point operation is greater than the magnitude allowed by the corresponding type. This value is defined as STATUS_FLOAT_OVERFLOW." )
    .Add( EXCEPTION_FLT_STACK_CHECK,          "The stack has overflowed or underflowed, because of a floating point operation. This value is defined as STATUS_FLOAT_STACK_CHECK." )
    .Add( EXCEPTION_FLT_UNDERFLOW,            "The exponent of a floating point operation is less than the magnitude allowed by the corresponding type. This value is defined as STATUS_FLOAT_UNDERFLOW." )
    .Add( EXCEPTION_GUARD_PAGE,               "The thread accessed memory allocated with the PAGE_GUARD modifier. This value is defined as STATUS_GUARD_PAGE_VIOLATION." )
    .Add( EXCEPTION_ILLEGAL_INSTRUCTION,      "The thread tries to execute an invalid instruction. This value is defined as STATUS_ILLEGAL_INSTRUCTION." )
    .Add( EXCEPTION_IN_PAGE_ERROR,            "The thread tries to access a page that is not present, and the system is unable to load the page. For example, this exception might occur if a network connection is lost while running a program over a network. This value is defined as STATUS_IN_PAGE_ERROR." )
    .Add( EXCEPTION_INT_DIVIDE_BY_ZERO,       "The thread attempts to divide an integer value by an integer divisor of 0 (zero). This value is defined as STATUS_INTEGER_DIVIDE_BY_ZERO." )
    .Add( EXCEPTION_INT_OVERFLOW,             "The result of an integer operation causes a carry out of the most significant bit of the result. This value is defined as STATUS_INTEGER_OVERFLOW." )
    .Add( EXCEPTION_INVALID_DISPOSITION,      "An exception handler returns an invalid disposition to the exception dispatcher. Programmers using a high-level language such as C should never encounter this exception. This value is defined as STATUS_INVALID_DISPOSITION." )
    .Add( EXCEPTION_INVALID_HANDLE,           "The thread used a handle to a kernel object that was invalid (probably because it had been closed.) This value is defined as STATUS_INVALID_HANDLE." )
    .Add( EXCEPTION_NONCONTINUABLE_EXCEPTION, "The thread attempts to continue execution after a non-continuable exception occurs. This value is defined as STATUS_NONCONTINUABLE_EXCEPTION." )
    .Add( EXCEPTION_PRIV_INSTRUCTION,         "The thread attempts to execute an instruction with an operation that is not allowed in the current computer mode. This value is defined as STATUS_PRIVILEGED_INSTRUCTION." )
    .Add( EXCEPTION_SINGLE_STEP,              "A trace trap or other single instruction mechanism signals that one instruction is executed. This value is defined as STATUS_SINGLE_STEP." )
    .Add( EXCEPTION_STACK_OVERFLOW,           "The thread uses up its stack. This value is defined as STATUS_STACK_OVERFLOW." );

Then in main or app init, I do this:

BOOL CMyApp::InitInstance()
{
    ExceptionHandlerInstaller ehi;
    // ...
}

Note that this translates structured exceptions to regular exceptions but handles terminate (which gets called, e.g., when a nothrow() function throws an exception) by simply printing an error message. It is highly unlikely that you want to use a single handler for all different types of errors, which is why they don't provide it.

这篇关于如何处理所有错误,包括内部C库错误,统一的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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