Michael Stum
Michael Stum

Reputation: 180944

How to properly create a custom exception with a message?

I'm new to C++ and I'm trying to create a custom exception that takes a message in its ctor.

What I have right now is this:

class LevelLoadException : public std::exception
{
public:
    LevelLoadException(std::string msg) : m_message(msg) { }
    const char * what () const throw ()
    {
        return m_message.c_str();
    }
private:
    std::string m_message;
};

In my calling code, I have this as part of a switch statements (c is a char, or more specifically, c = line[x]; where x is an int and line is a std::string);

default:
    throw LevelLoadException("Invalid Character in Level: " + c);

The problem is that my Exception gets a completely unrelated string (that's part of the same method that throws: throw std::exception("There is more than 1 player start in the level.")).

I have excluded a logic bug - my program reaches the line where the correct exception with the correct string is thrown. So I'm pretty sure it's a lifetime/memory management problem.

To my understanding, C++ is copy-by-value by default. So I thought that calling the ctor of LevelLoadException would immediately copy the string. But it seems that there is some pointer stuff going on, since the string that I'm building seems like a C string (const char*).

I looked at the std::exception class, and this takes a const char* const& as the message and then does some C-like strcopy/malloc under the hood (MSVC / Visual Studio 2012 Update 4).

I'm not a hundred percent sure what I actually need. I think what I want is a string that's built in the caller, then moved/copied into the Exception (which now owns a copy of the string that's only owned by the exception) and then the one in the caller is destroyed when it's out of scope.

Can someone give me a pointer to what I should be doing differently to do this properly?

Upvotes: 7

Views: 3852

Answers (1)

Igor Tandetnik
Igor Tandetnik

Reputation: 52471

"Invalid Character in Level: " + c doesn't do what you think it does. It means "a char* pointer that is offset by N bytes from the beginning of the string literal", where N is the ASCII code of the character stored in c. Chances are high the literal is actually shorter than N characters, in which case this program contains a buffer overrun and exhibits undefined behavior.

Make it

throw LevelLoadException(std::string("Invalid Character in Level: ") + c);

Upvotes: 13

Related Questions