I'm looking at modifying the MS structured exception-to-exception mapping code we have to use the new C++11 error_code/error_condition/exception mechanisim.
My understanding is that the general philosiphy is that you should try to map your error codes to std::error_condition codes first, failing that, make your own custom error_condition codes.
The issue I'm seeing that the std::errc is pretty much tailored to work well with POSIX errors. If I'm getting codes from a source that has a fairly differernt error universe than your typical OS call, it just doesn't map well.
For example, lets take Microsoft's SEH codes. These come from the OS, so in theory it should map as well as about anything outside POSIX can. But it sure doesn't seem to map well at all:
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?
So what would the best way to attack this?
First as commented by @JamesMcNellis some of this exceptions are very dangerous and it may be better to let OS handle them and terminate your program, since those errors are usually an error in your code. But may be you want to handle them and write something like a crash report possibly with a dump of stack and registers.
Beside that std::error_condition
and std::error_code
is not designed to only work with POSIX
errors. Their structure is designed in a way that can handle any case that an int
value that is equal to 0 indicate a success and otherwise an error, so you may write a completely valid code that use them with std::error_code
and std::error_condition
but you should drive a class from std::error_category
and implement its virtual functions to provide explanation of your error codes that matched with your error codes(in your case NT status codes):
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() );
}