Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to avoid putting std::string in exception class?

Here is my exception class:

class Win32Failure : public std::exception
{
public:
    Win32Failure( char const* win32_function_name, LONG error_code );

    char const* win32_function_name() const { return win32_function_name_; }
    LONG error_code() const { return error_code_; }

    virtual char const* what() const;

private:

    std::string GetFormattedMessage() const;

    char const* win32_function_name_;
    LONG error_code_;
    std::string error_text_;
};

Win32Failure::Win32Failure( char const* win32_function_name, LONG error_code )
    : error_code_(error_code)
    , win32_function_name_(win32_function_name)
{
    std::stringstream error_msg;
    error_msg   << win32_function_name << " failed with code: "
                << error_code << " (" << GetFormattedMessage() << ")"
                ;

    error_text_ = error_msg.str();
}

std::string Win32Failure::GetFormattedMessage() const
{
    TCHAR message_buffer[1000];

    FormatMessage(
        //FORMAT_MESSAGE_ALLOCATE_BUFFER |
        FORMAT_MESSAGE_FROM_SYSTEM |
        FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL,
        error_code_,
        0, // Default language
        reinterpret_cast<LPTSTR>(&message_buffer),
        sizeof(message_buffer) / sizeof(TCHAR),
        NULL
        );

    return std::string(message_buffer);
}

char const* Win32Failure::what() const
{
    return error_text_.c_str();
}

The boost exception guidelines recommend not placing any objects that allocate memory as members of my exception class. In this case, the usage of std::string violates this. I respect the rule for this, however I can't think of a way to implement the what() override without using std::string to manage the memory (versus requiring the caller to manage it for me).

I could use a fixed-size buffer as a member and use C library functions (like snprintf()) to do the job, but this isn't very idiomatic to C++ and thus not an ideal solution.

Is this a suitable implementation of an exception class? If not, what improvements can be made?

like image 531
void.pointer Avatar asked Feb 22 '12 22:02

void.pointer


People also ask

Can STD string throw exceptions?

Can shrinking a std::string throw an exception? The question is whether this function can throw an exception. Can the call to resize throw an exception when used to make a string smaller? And the answer appears to be yes, at least in C++17.

Why are C++ exceptions bad?

The main reason C++ exceptions are so often forbidden is that it's very hard to write exception safe C++ code. Exception safety is not a term you hear very often, but basically means code that doesn't screw itself up too badly if the stack is unwound.

Does throwing an exception stop execution C++?

throw usually causes the function to terminate immediately, so you even if you do put any code after it (inside the same block), it won't execute. This goes for both C++ and C#.

What is std :: exception in C++?

std::exceptionBase class for standard exceptions. All objects thrown by components of the standard library are derived from this class. Therefore, all standard exceptions can be caught by catching this type by reference. It is declared as: C++98.


1 Answers

For what it's worth, all of the exception types defined in <stdexcept> take std::string as arguments. This could be interpreted by the library designers that it is "ok". I think the main argument against this is if you're in a memory constrained environment, you may not be able to allocate memory to throw your exception.

like image 114
Nathan Ernst Avatar answered Oct 24 '22 04:10

Nathan Ernst