Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Turning GetLastError() into an exception

I have a Visual Studio 2008 C++ project that uses a Win32Exception class in cases where there is an exceptional error. The Win32Exception class looks like this:

/// defines an exception based on Win32 error codes. The what() function will
/// return a formatted string returned from FormatMessage()
class Win32Exception : public std::runtime_error
{
public:
    Win32Exception() : std::runtime_error( ErrorMessage( &error_code_ ) )
    {
    };

    virtual ~Win32Exception() { };

    /// return the actual error code
    DWORD ErrorCode() const throw() { return error_code_; };

private:

    static std::string ErrorMessage( DWORD* error_code )
    {
        *error_code = ::GetLastError();

        std::string error_messageA;
        wchar_t* error_messageW = NULL;
        DWORD len = ::FormatMessageW( FORMAT_MESSAGE_FROM_SYSTEM | 
                                      FORMAT_MESSAGE_ALLOCATE_BUFFER |
                                      FORMAT_MESSAGE_IGNORE_INSERTS,
                                      NULL,
                                      *error_code,
                                      MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),
                                      reinterpret_cast< LPWSTR >( &error_messageW ),
                                      0,
                                      NULL );
        if( NULL != error_messageW )
        {
            // this may generate a C4244 warning. It is safe to ignore.
            std::copy( error_messageW, 
                       error_messageW + len, 
                       std::back_inserter( error_messageA ) );
            ::LocalFree( error_messageW );
        }
        return error_messageA;
    };

    /// error code returned by GetLastError()
    DWORD error_code_;

}; // class Win32Exception

The class works well in the situations it has been used in. What I would like to know is if there are any obvious cases where this will fail that I should be aware of. Any other gotchas, caveats, or general suggestions on improvements are welcome.

Please note that the boost library is not an option for this code.

like image 872
PaulH Avatar asked Dec 17 '10 22:12

PaulH


People also ask

What can GetLastError () function do explain?

An application can retrieve the last-error code by using the GetLastError function; the error code may tell more about what actually occurred to make the function fail. The documentation for system functions will indicate the conditions under which the function sets the last-error code.

What is the return type of GetLastError () function?

GetLastError() returns an integer value, not a text message.

How do I get error messages in C++?

C++ perror() The perror() function in C++ prints the error message to stderr based on the error code currently stored in the system variable errno.


1 Answers

  • This has already done by several people, including yours truly
    • https://github.com/BillyONeal/Instalog/blob/master/LogCommon/Win32Exception.hpp
    • https://github.com/BillyONeal/Instalog/blob/master/LogCommon/Win32Exception.cpp
  • Ironically, your code is not exception safe.

    if( NULL != error_messageW )
    {
        // this may generate a C4244 warning. It is safe to ignore.
        std::copy( error_messageW, 
                   error_messageW + len, 
                   std::back_inserter( error_messageA ) );
        ::LocalFree( error_messageW );
    }
    

Note that if the back_inserter causes std::bad_alloc to be thrown, the memory allocated inside FormatMessage is leaked.

like image 118
Billy ONeal Avatar answered Nov 05 '22 14:11

Billy ONeal