17

I'm not sure that my custom exception approach is correct. What I want to do is to throw exceptions with custom messages but it seems that I created a memory leak...

class LoadException: public std::exception { private: const char* message; public: LoadException(const std::string message); virtual const char* what() const throw(); }; LoadException::LoadException(const std::string message) { char* characters = new char[message.size() + 1]; std::copy(message.begin(), message.end(), characters); characters[message.size()] = '\0'; this->message = characters; } 

I use it as follows:

void array_type_guard(Local<Value> obj, const std::string path) { if (!obj->IsArray()) { throw LoadException(path + " is not an array"); } } try { objects = load_objects(); } catch (std::exception& e) { ThrowException(Exception::TypeError(String::New(e.what()))); return scope.Close(Undefined()); } 

I afraid that the array created in constructor is never deleted. But I'm not sure how to delete it - should I add destructor or maybe use completely different approach?

Update:

I've actually tried to use the string class as follows:

class LoadException: public std::exception { private: const char* msg; public: LoadException(const std::string message); virtual const char* what() const throw(); }; LoadException::LoadException(const std::string message) { msg = message.c_str(); } const char* LoadException::what() const throw() { return msg; } 

But cannot get the error message then - some random output is displayed when I print the "what()".

5
  • 2
    just use string to store the message. Or is there a reason for the char *? Commented Jul 3, 2013 at 2:48
  • No, there is no reason for char*. I changed the code to string. Thanks. Commented Jul 3, 2013 at 3:07
  • Or just wite a destructor that deletes the allocated character array. Commented Jul 3, 2013 at 3:25
  • related stackoverflow.com/questions/2715386/… Commented Feb 19, 2017 at 22:36
  • std::exception already guarantees the storage of a custom message. Why not re-use. Even if derive from std::exception you can still use that functionality. Commented Sep 26, 2020 at 19:49

3 Answers 3

41

How about
throw std::runtime_error("My very own message");

Sign up to request clarification or add additional context in comments.

Comments

24

You can take advantage of std:string

class LoadException: public std::exception { private: std::string message_; public: explicit LoadException(const std::string& message); const char* what() const noexcept override { return message_.c_str(); } }; LoadException::LoadException(const std::string& message) : message_(message) { } 

Then the C++ scoping will take care of cleaning things up for you

5 Comments

Would be better to pass by non-const value and move construct message_
Thanks. It works this way, but I do not know why... It looks like the string is copied to the exception object. Am I right?
It works because string allocates and deallocates buffer on it's own. It does exactly the same as you did, but additionally it deletes allocated memory in it's destructor.
When the exception goes out of scope, the members of the exception have their destructor called. The string class takes care of managing its own buffer, so it cleans up after itself when its destructor is called, and this happens when the LoadException goes out of scope.
You actually also need to specify an override LoadException::~LoadException() throw() {}, otherwise you have a looser throw specifier error.
2

In the constructor I have

Printer::Printer(boost::asio::io_service& io, unsigned int interval) { if (interval < 1) { throw std::runtime_error("Interval can't be less than one second"); } } 

And when creating the object

try { Printer p{io, 0}; } catch (std::exception& e) { std::cerr << e.what() << std::endl; } 

the program will exit with the message thrown.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.