【问题标题】:Mapping external error codes to std::error_condition将外部错误代码映射到 std::error_condition
【发布时间】:2012-10-26 19:57:08
【问题描述】:

我正在考虑修改我们必须使用新的 C++11 error_code/error_condition/exception mechanisim 的 MS 结构化异常到异常映射代码。

我的理解是,一般理念是您应该首先尝试将错误代码映射到 std::error_condition 代码,如果失败,请制作您自己的自定义 error_condition 代码。

我看到std::errc 非常适合处理 POSIX 错误的问题。如果我从具有与典型操作系统调用完全不同的错误范围的源获取代码,则它的映射不正确。

例如,我们以Microsoft's SEH codes 为例。这些来自操作系统,因此理论上它应该映射以及 POSIX 之外的任何内容。但它确实似乎根本无法很好地映射:

EXCEPTION_ACCESS_VIOLATION  = permission_denied
EXCEPTION_ARRAY_BOUNDS_EXCEEDED = argument_out_of_domain perhaps?
EXCEPTION_BREAKPOINT = ?
EXCEPTION_DATATYPE_MISALIGNMENT = ?
EXCEPTION_FLT_DENORMAL_OPERAND = ? 
EXCEPTION_FLT_DIVIDE_BY_ZERO = ?
EXCEPTION_FLT_INEXACT_RESULT = ? 
EXCEPTION_FLT_INVALID_OPERATION = ?
EXCEPTION_FLT_OVERFLOW = ?
EXCEPTION_FLT_STACK_CHECK = ?
EXCEPTION_FLT_UNDERFLOW = ?
EXCEPTION_GUARD_PAGE = ?
EXCEPTION_ILLEGAL_INSTRUCTION = ?
EXCEPTION_IN_PAGE_ERROR = ?
EXCEPTION_INT_DIVIDE_BY_ZERO = ?
EXCEPTION_INT_OVERFLOW = value_too_large perhaps, but then what do I use for _STACK_OVERFLOW?
EXCEPTION_INVALID_DISPOSITION = ?
EXCEPTION_INVALID_HANDLE = ? 
EXCEPTION_NONCONTINUABLE_EXCEPTION = ? 
EXCEPTION_PRIV_INSTRUCTION = ?
EXCEPTION_SINGLE_STEP = ?
EXCEPTION_STACK_OVERFLOW = value_too_large perhaps, but then what do I use for _INT_OVERFLOW?

那么攻击这个的最好方法是什么?

【问题讨论】:

  • 尝试处理其中的大部分是极其危险的。例如,如果发生访问冲突或遇到非法指令,您的程序将被彻底破坏。对于其中大多数,处理异常的最佳方法是根本不处理它(并让应用程序终止)。当然,将 AV 映射到 permission_denied 根本不是一个好主意。大多数程序不需要处理结构化异常(在少数情况下尝试处理结构化异常可能很有用,但这些情况非常罕见)。
  • @JamesMcNellis - 我相信当 SEH 异常发生时我们现在所做的就是吐出适当的错误消息,然后尽可能好地关闭线程。我们有一个大型应用程序,它执行由许多不同模块组编码的大量复杂数学,因此能够吐出导致崩溃的浮点错误类型对我们非常有帮助,也许是哪一行发生在死前。
  • @T.E.D.:我一直在想这个,看来关键是要新建一个error_category类,但是不知道是应该做实例还是派生类型或如何使用它或任何东西:/ 编辑:我找到了一个教程! blog.think-async.com/2010/04/…
  • @MooingDuck - 我自己一直在写那篇非常好的 5 部分文章。很好,不是吗?

标签: c++ c++11 structured-exception


【解决方案1】:

首先正如@JamesMcNellis 评论的那样,其中一些异常非常危险,让操作系统处理它们并终止您的程序可能会更好,因为这些错误通常是代码中的错误。但是您可能想处理它们并编写崩溃报告之类的内容,可能带有堆栈和寄存器的转储。

除此之外,std::error_conditionstd::error_code 并非设计为仅适用于 POSIX 错误。它们的结构设计为可以处理任何情况,即等于 0 的 int 值表示成功或错误,因此您可以编写一个完全有效的代码,将它们与 std::error_codestd::error_condition 一起使用但是您应该从std::error_category 驱动一个类并实现它的虚函数,以提供与您的错误代码匹配的错误代码的解释(在您的情况下为 NT 状态代码):

class NT_status_code_error_category : std::error_category {
public:
    const char* name() const {return "NT status code";}
    std::string message( int errCode ) const {
        switch( errCode ) {
        case EXCEPTION_ACCESS_VIOLATION: return "Access violation";
        // a couple of other error codes will be handled here
        default: return "Unknown status code";
        }
    }
    std::error_condition default_error_condition( int errCode ) const {
    return std::error_condition( errCode, *this );
}
};
inline NT_status_code_error_category const& NT_status_code_category() {
    static NT_status_code_error_category res;
    return res;
}

inline std::error_code make_NT_status_error_code( int status ) {
    return std::error_code( status, NT_status_code_category() );
}
inline std::error_condition make_NT_status_error_condition( int status ) {
    return std::error_condition( status, NT_status_code_category() );
}

【讨论】:

  • 好的。但是在我的情况下,我自己的错误条件和我的错误代码是合理的吗?例如,我可能在处理方面的唯一区别是它是浮点错误还是非浮点错误。 (即便如此,差异可能只是嵌入在错误消息中 - message())。
  • 我认为正如您在问题中已经说过的那样,Microsoft SEH 来自操作系统,就像任何其他错误代码一样,它们应该映射到 std::error_code,所以如果合乎逻辑,就有一个 @987654331 @ 用于POSIXWin32 错误代码,我认为值得拥有error_condition 用于SEH 代码
猜你喜欢
  • 2019-05-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-05
  • 2012-12-26
  • 2019-01-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多