How to properly create a custom exception with a message? - c++

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?

"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);

Related

How to solve this Valgrind error due to c_str() [duplicate]

This is an example of what I often do when I want to add some information to an exception:
std::stringstream errMsg;
errMsg << "Could not load config file '" << configfile << "'";
throw std::exception(errMsg.str().c_str());
Is there a nicer way to do it?
The standard exceptions can be constructed from a std::string:
#include <stdexcept>
char const * configfile = "hardcode.cfg";
std::string const anotherfile = get_file();
throw std::runtime_error(std::string("Failed: ") + configfile);
throw std::runtime_error("Error: " + anotherfile);
Note that the base class std::exception can not be constructed thus; you have to use one of the concrete, derived classes.
Here is my solution:
#include <stdexcept>
#include <sstream>
class Formatter
{
public:
Formatter() {}
~Formatter() {}
template <typename Type>
Formatter & operator << (const Type & value)
{
stream_ << value;
return *this;
}
std::string str() const { return stream_.str(); }
operator std::string () const { return stream_.str(); }
enum ConvertToString
{
to_str
};
std::string operator >> (ConvertToString) { return stream_.str(); }
private:
std::stringstream stream_;
Formatter(const Formatter &);
Formatter & operator = (Formatter &);
};
Example:
throw std::runtime_error(Formatter() << foo << 13 << ", bar" << myData); // implicitly cast to std::string
throw std::runtime_error(Formatter() << foo << 13 << ", bar" << myData >> Formatter::to_str); // explicitly cast to std::string
There are different exceptions such as runtime_error, range_error, overflow_error, logic_error, etc.. You need to pass the string into its constructor, and you can concatenate whatever you want to your message. That's just a string operation.
std::string errorMessage = std::string("Error: on file ")+fileName;
throw std::runtime_error(errorMessage);
You can also use boost::format like this:
throw std::runtime_error(boost::format("Error processing file %1") % fileName);
The following class might come quite handy:
struct Error : std::exception
{
char text[1000];
Error(char const* fmt, ...) __attribute__((format(printf,2,3))) {
va_list ap;
va_start(ap, fmt);
vsnprintf(text, sizeof text, fmt, ap);
va_end(ap);
}
char const* what() const throw() { return text; }
};
Usage example:
throw Error("Could not load config file '%s'", configfile.c_str());
Use string literal operator if C++14 (operator ""s)
using namespace std::string_literals;
throw std::exception("Could not load config file '"s + configfile + "'"s);
or define your own if in C++11. For instance
std::string operator ""_s(const char * str, std::size_t len) {
return std::string(str, str + len);
}
Your throw statement will then look like this
throw std::exception("Could not load config file '"_s + configfile + "'"_s);
which looks nice and clean.
Maybe this?
throw std::runtime_error(
(std::ostringstream()
<< "Could not load config file '"
<< configfile
<< "'"
).str()
);
It creates a temporary ostringstream, calls the << operators as necessary and then you wrap that in round brackets and call the .str() function on the evaluated result (which is an ostringstream) to pass a temporary std::string to the constructor of runtime_error.
Note: the ostringstream and the string are r-value temporaries and so go out of scope after this line ends. Your exception object's constructor MUST take the input string using either copy or (better) move semantics.
Additional: I don't necessarily consider this approach "best practice", but it does work and can be used at a pinch. One of the biggest issues is that this method requires heap allocations and so the operator << can throw. You probably don't want that happening; however, if your get into that state your probably have way more issues to worry about!
There are two points to answer in regards to what you want:
1.
The first point is that the nicer way is creating special types (classes) for custom exceptions and passing parameters as fields of the classes.
Something like the following:
class BaseFor_Exceptions : public std::exception {
protected:
BaseFor_Exceptions();
};
class Exception1 : public BaseFor_Exceptions {
public:
Exception1(uint32_t value1);
private:
uint32_t value1;
};
throw Exception1(0);
The second point is that you are performing memory allocations when preparing the exception object because of trying to pass a value of variable size (filename).
There is a possibility (when changing objects of the both std::string and std::stringstream ) of std::bad_alloc exception to be thrown in the process of it, so that you fail to prepare or throw (*) your exception – you will lose the info and the state.
In a well-designed program it is easy to avoid memory allocation when preparing or handling an exception. All that you need is just:
either guarantee the value is still life when handling the exception and pass some kind of link to the value as a part of the exception – either reference or some kind (most likely smart) of pointer,
or get the value when handling the exception using the exception type info or/and fixed-size values;
for example,
} catch (const ConfigurationLoadError & ex) {
std::cerr
<< “Some message 1 ”
<< serviceLocator1.SomeGetMethod1().Get_ConfigurationFileName();
} catch (const SomeException & ex) {
std::cerr
<< “Some message 2 ”
<< serviceLocator1.SomeGetMethod2().GetEventDetailsString(ex.Get_Value1());
}
Of course, you always have an option to accept buffer size limitations and use a pre-allocated buffer.
Also, please note that the type (classes) used for exceptions are not permitted to throw exceptions out of their copy constructors since, if the initial exception is attempted to be caught by value, a call of copy constructor is possible (in case is not elided by the compiler) and this additional exception will interrupt the initial exception handling before the initial exception is caught, which causes calling std::terminate.
Since C++11 compilers are permitted to eliminate the copying in some cases when catching, but both the elision is not always sensible and, if sensible, it is only permission but not obligation (see https://en.cppreference.com/w/cpp/language/copy_elision for details; before C++11 the standards of the language didn’t regulate the matter).
'*' Also, you should avoid exceptions (will call them the additional) to be thrown out of constructors and move constructors of your types (classes) used for exceptions (will call them initial) since the constructors and move constructors could be called when throwing objects of the types as initial exceptions, then throwing out an additional exception would prevent creation of an initial exception object, and the initial would just be lost. As well as an additional exception from a copy constructor, when throwing an initial one, would cause the same.
Ran into a similar issue, in that creating custom error messages for my custom exceptions make ugly code. This was my solution:
class MyRunTimeException: public std::runtime_error
{
public:
MyRunTimeException(const std::string &filename):std::runtime_error(GetMessage(filename)) {}
private:
static std::string GetMessage(const std::string &filename)
{
// Do your message formatting here.
// The benefit of returning std::string, is that the compiler will make sure the buffer is good for the length of the constructor call
// You can use a local std::ostringstream here, and return os.str()
// Without worrying that the memory is out of scope. It'll get copied
// You also can create multiple GetMessage functions that take all sorts of objects and add multiple constructors for your exception
}
}
This separates the logic for creating the messages. I had originally thought about overriding what(), but then you have to capture your message somewhere. std::runtime_error already has an internal buffer.
Whenever I need a custom message to be thrown in an exception, I construct a C-style string with snprintf() and pass it to the exception constructor.
if (problem_occurred) {
char buffer[200];
snprintf(buffer, 200, "Could not load config file %s", configfile);
string error_mesg(buffer);
throw std::runtime_error(error_mesg);
}
I'm not sure if the extra string string error_mesg(buffer) is necessary. I reason that the buffer is on stack memory, and if the exception catcher keeps running, then allowing the catcher to keep a reference to a stack-allocated C string is problematic. Instead, passing a string to the exception will invoke copy-by-value, and the buffer array will be deep-copied.

C++ Weird string/char* exception behaviour

Well here is my exception code :
class OptionNotFoundError: public std::exception {
public:
OptionNotFoundError(std::string option, int position) throw()
: option(option), position(position) {}
OptionNotFoundError(char option_, int position) throw()
: position(position) { option.push_back(option_); }
virtual ~OptionNotFoundError() throw() {}
virtual const char* what() const throw() {
std::string what_str = "Option '" + option + "' not found in position " + std::to_string(position);
std::cout << what_str.c_str() << std::endl;
return what_str.c_str();;
}
std::string option;
int position;
};
When the exception is thrown, here is what I get in the terminal :
terminate called after throwing an instance of 'Args::OptionNotFoundError'
Option 'c' not found in position 1
what():
So the cout works fine, but… not the return. If I use return "smth" it works fine.
Weirder : if I replace what_str definition with
std::string what_str = "test";
I get
terminate called after throwing an instance of 'Args::OptionNotFoundError'
test
what(): x�zL�
Again, the cout<< works fine. But the return… Not so much. Is this some encoding error ?
return what_str.c_str();;
c_str() returns a pointer to the internal contents of the std::string.
This pointer remains valid only until either
The std::string object gets destroyed.
The std::string object gets modified.
The std::string object from which this c_str() pointer is obtained gets destroyed when your function returns.
This results in undefined behavior.
The const char * that your function returns is not valid. It's pointing to the internal contents of a destroyed object.
For the 1st case, note that what_str is a local variable inside what(), it'll be destroyed when get out of the function scope, then the pointer returned by it becomes dangled, dereference on it leads to UB.
For the 2nd case, returning "smth" works fine, because "smth" is a const char[5], which is a string literal,
String literals have static storage duration, and thus exist in memory for the life of the program.
For the 3rd case,
if i replace what_str definition with
std::string what_str = "test";
It doesn't work, because what_str is still a local std::string, the problem is same with the 1st case.

std::exception using message from local object

Is the following code safely throwing an exception with custom message?
#include <exception>
#include <sstream>
#include <string>
#include <iostream>
int main() {
try {
std::ostringstream msg;
msg << "give me " << 5;
throw std::exception(msg.str().c_str());
} catch (std::exception& e) {
std::cout << "exception: " << e.what();
}
}
With VC++-2008 this gives:
exception: give me 5
But now I wonder why the message "give me 5" from the local object msg is still available in the catch-block? By the time the message is printed both the stream- and the temporary string-object should have been deleted? Btw: This way of generating a message for an exception seems also to work accross several functions and also if new memory is allocated in the catch-block before printing the exception.
Or is it necessary to define a custom exception class with a std::string member in order to safely keep the message until printing it.
It's perfectly safe. The constructor that takes a C string as a single parameter makes a copy of the string. The constructor that takes a C string and a length parameter allow you to specify no memory be allocated and stores a pointer to the string (the length parameter is ignored).
Note that these two constructors are extensions to the std::exception class and are not standard. Also be aware that the constructor that takes a C string as a single parameter is not marked as explicit.
It's OK.
Per §15.1/3:
Throwing an exception copy-initializes (8.5, 12.8) a temporary object,
called the exception object.
and §15.1/4:
The memory for the exception object is allocated in an unspecified
way, except as noted in 3.7.4.1. If a handler exits by rethrowing,
control is passed to another handler for the same exception. The
exception object is destroyed after either the last remaining active
handler for the exception exits by any means other than rethrowing...
so after throw expression:
the expression will be copied (new object will be created by copy constructor) and you shouldn't worry about the local object.
About the msg and const char* which you're worrying... here is Microsoft's implementation:
exception::exception(const char * const & _What)
: _Mywhat(NULL), _Mydofree(false)
{
_Copy_str(_What);
//^^^^^^^^^^^^^^^^^
}
void exception::_Copy_str(const char * _What)
{
if (_What != NULL)
{
const size_t _Buf_size = strlen(_What) + 1;
_Mywhat = static_cast<char *>(malloc(_Buf_size));
if (_Mywhat != NULL)
{
_CRT_SECURE_STRCPY(const_cast<char *>(_Mywhat), _Buf_size, _What);
//^^^^^^^^^^^^^^^^^^
_Mydofree = true;
}
}
}
It copies the _What not just storing the pointer.
No, it's not safe, because std::exception doesn't have a constructor taking a char* in the standard. You are using an MS extension. To make it portable and safe, use std::runtime_error instead, to which you can pass a std::string in the ctor.

How to throw std::exceptions with variable messages?

This is an example of what I often do when I want to add some information to an exception:
std::stringstream errMsg;
errMsg << "Could not load config file '" << configfile << "'";
throw std::exception(errMsg.str().c_str());
Is there a nicer way to do it?
The standard exceptions can be constructed from a std::string:
#include <stdexcept>
char const * configfile = "hardcode.cfg";
std::string const anotherfile = get_file();
throw std::runtime_error(std::string("Failed: ") + configfile);
throw std::runtime_error("Error: " + anotherfile);
Note that the base class std::exception can not be constructed thus; you have to use one of the concrete, derived classes.
Here is my solution:
#include <stdexcept>
#include <sstream>
class Formatter
{
public:
Formatter() {}
~Formatter() {}
template <typename Type>
Formatter & operator << (const Type & value)
{
stream_ << value;
return *this;
}
std::string str() const { return stream_.str(); }
operator std::string () const { return stream_.str(); }
enum ConvertToString
{
to_str
};
std::string operator >> (ConvertToString) { return stream_.str(); }
private:
std::stringstream stream_;
Formatter(const Formatter &);
Formatter & operator = (Formatter &);
};
Example:
throw std::runtime_error(Formatter() << foo << 13 << ", bar" << myData); // implicitly cast to std::string
throw std::runtime_error(Formatter() << foo << 13 << ", bar" << myData >> Formatter::to_str); // explicitly cast to std::string
There are different exceptions such as runtime_error, range_error, overflow_error, logic_error, etc.. You need to pass the string into its constructor, and you can concatenate whatever you want to your message. That's just a string operation.
std::string errorMessage = std::string("Error: on file ")+fileName;
throw std::runtime_error(errorMessage);
You can also use boost::format like this:
throw std::runtime_error(boost::format("Error processing file %1") % fileName);
The following class might come quite handy:
struct Error : std::exception
{
char text[1000];
Error(char const* fmt, ...) __attribute__((format(printf,2,3))) {
va_list ap;
va_start(ap, fmt);
vsnprintf(text, sizeof text, fmt, ap);
va_end(ap);
}
char const* what() const throw() { return text; }
};
Usage example:
throw Error("Could not load config file '%s'", configfile.c_str());
Use string literal operator if C++14 (operator ""s)
using namespace std::string_literals;
throw std::exception("Could not load config file '"s + configfile + "'"s);
or define your own if in C++11. For instance
std::string operator ""_s(const char * str, std::size_t len) {
return std::string(str, str + len);
}
Your throw statement will then look like this
throw std::exception("Could not load config file '"_s + configfile + "'"_s);
which looks nice and clean.
Maybe this?
throw std::runtime_error(
(std::ostringstream()
<< "Could not load config file '"
<< configfile
<< "'"
).str()
);
It creates a temporary ostringstream, calls the << operators as necessary and then you wrap that in round brackets and call the .str() function on the evaluated result (which is an ostringstream) to pass a temporary std::string to the constructor of runtime_error.
Note: the ostringstream and the string are r-value temporaries and so go out of scope after this line ends. Your exception object's constructor MUST take the input string using either copy or (better) move semantics.
Additional: I don't necessarily consider this approach "best practice", but it does work and can be used at a pinch. One of the biggest issues is that this method requires heap allocations and so the operator << can throw. You probably don't want that happening; however, if your get into that state your probably have way more issues to worry about!
There are two points to answer in regards to what you want:
1.
The first point is that the nicer way is creating special types (classes) for custom exceptions and passing parameters as fields of the classes.
Something like the following:
class BaseFor_Exceptions : public std::exception {
protected:
BaseFor_Exceptions();
};
class Exception1 : public BaseFor_Exceptions {
public:
Exception1(uint32_t value1);
private:
uint32_t value1;
};
throw Exception1(0);
The second point is that you are performing memory allocations when preparing the exception object because of trying to pass a value of variable size (filename).
There is a possibility (when changing objects of the both std::string and std::stringstream ) of std::bad_alloc exception to be thrown in the process of it, so that you fail to prepare or throw (*) your exception – you will lose the info and the state.
In a well-designed program it is easy to avoid memory allocation when preparing or handling an exception. All that you need is just:
either guarantee the value is still life when handling the exception and pass some kind of link to the value as a part of the exception – either reference or some kind (most likely smart) of pointer,
or get the value when handling the exception using the exception type info or/and fixed-size values;
for example,
} catch (const ConfigurationLoadError & ex) {
std::cerr
<< “Some message 1 ”
<< serviceLocator1.SomeGetMethod1().Get_ConfigurationFileName();
} catch (const SomeException & ex) {
std::cerr
<< “Some message 2 ”
<< serviceLocator1.SomeGetMethod2().GetEventDetailsString(ex.Get_Value1());
}
Of course, you always have an option to accept buffer size limitations and use a pre-allocated buffer.
Also, please note that the type (classes) used for exceptions are not permitted to throw exceptions out of their copy constructors since, if the initial exception is attempted to be caught by value, a call of copy constructor is possible (in case is not elided by the compiler) and this additional exception will interrupt the initial exception handling before the initial exception is caught, which causes calling std::terminate.
Since C++11 compilers are permitted to eliminate the copying in some cases when catching, but both the elision is not always sensible and, if sensible, it is only permission but not obligation (see https://en.cppreference.com/w/cpp/language/copy_elision for details; before C++11 the standards of the language didn’t regulate the matter).
'*' Also, you should avoid exceptions (will call them the additional) to be thrown out of constructors and move constructors of your types (classes) used for exceptions (will call them initial) since the constructors and move constructors could be called when throwing objects of the types as initial exceptions, then throwing out an additional exception would prevent creation of an initial exception object, and the initial would just be lost. As well as an additional exception from a copy constructor, when throwing an initial one, would cause the same.
Ran into a similar issue, in that creating custom error messages for my custom exceptions make ugly code. This was my solution:
class MyRunTimeException: public std::runtime_error
{
public:
MyRunTimeException(const std::string &filename):std::runtime_error(GetMessage(filename)) {}
private:
static std::string GetMessage(const std::string &filename)
{
// Do your message formatting here.
// The benefit of returning std::string, is that the compiler will make sure the buffer is good for the length of the constructor call
// You can use a local std::ostringstream here, and return os.str()
// Without worrying that the memory is out of scope. It'll get copied
// You also can create multiple GetMessage functions that take all sorts of objects and add multiple constructors for your exception
}
}
This separates the logic for creating the messages. I had originally thought about overriding what(), but then you have to capture your message somewhere. std::runtime_error already has an internal buffer.
Whenever I need a custom message to be thrown in an exception, I construct a C-style string with snprintf() and pass it to the exception constructor.
if (problem_occurred) {
char buffer[200];
snprintf(buffer, 200, "Could not load config file %s", configfile);
string error_mesg(buffer);
throw std::runtime_error(error_mesg);
}
I'm not sure if the extra string string error_mesg(buffer) is necessary. I reason that the buffer is on stack memory, and if the exception catcher keeps running, then allowing the catcher to keep a reference to a stack-allocated C string is problematic. Instead, passing a string to the exception will invoke copy-by-value, and the buffer array will be deep-copied.

c++ cout and char-pointers, something I'm missing with pointers

I'm trying to write a piece of code for a kind of tree I'm making, and if a node doesn't exist i would like to throw an exception showing what node doesn't exist. Ie:
Trie t = Trie();
try {
t.get('a');
} catch(NoSuchNode e) {
cout << e.what() << endl;
}
this code should just do nothing if the node exists, otherwise print the error given, here's my code for the exception (i use the std::exception because that seemed like a good idea):
class NoSuchNode : public std::exception
{
private:
char *_node_name;
public:
NoSuchNode(const char *node_name) { _node_name = new char(*node_name); }
virtual const char* what() const throw()
{
std::stringstream ss;
ss << "There exists no node for: " << _node_name << ".";
const std::string& tmp = ss.str();
return tmp.c_str();
}
};
And this works as it should, valgrind doesn't give any errors on invalid reads either so it's fine i suppose? Now to my question, before i came up with this solution i had just changed:
_node_name = new char(*node_name);
to:
_node_name = node_name;
so that i don't need to allocate more space for it. The problem is that sometimes it doesn't really print any good data and sometimes the one char and even more after that. Not really what i would have expected. Also, valgrind complained that i read past the memory i could use. Why is this? My bet is that if std::string just get's a pointer to a char it thinks is a null-terminated string and therefore tries to read from the start of the memory until it finds the null-character? Is this correct and what's the proper way to solve this problem? Should i just pass the data by value as I'm pretty much doing?
Added:
Each node should hold just one char and nothing more, everything passed by char is just one char and nothing else. So i'm not having a string in chars so to say.
So it turns out what i was really interested in was how the streams handle char* input.
Thanks for the answers!
If something other is wrong in my code and you have the time please do tell me!
Thanks in advance!
new char(*node_name) allocates a single character corresponding to the first character of node_name. Not a string. When you use it like a NULL-terminated C string, the terminator byte is missing and you'll get garbage.
A char* is special for std::cout and other streams because it means "null-terminated C string". You'll have to dereference it (<< *_node_name <<) or, like hmjd suggests, simply use a single char (char node_name).
When you use node_name without reallocation, you run the risk that the space your pointer is referring to is already gone when you need it. You don't own the pointed-to memory, so you should either use it immediately or make a copy.
In general, writing own exception classes is not easy, and there is much to consider. In your case, just derive from std::logic_error or std::runtime_error, and let them handle the strings.
Why do you use pointers at all? Your node name is a single char, treat it as such.
class NoSuchNode : public std::exception
{
private:
char _node_name;
public:
NoSuchNode(char node_name) : _node_name(node_name) { }
virtual const char* what() const throw()
{
std::stringstream ss;
ss << "There exists no node for: " << _node_name << ".";
const std::string& tmp = ss.str();
return tmp.c_str();
}
};
(I’ve replaced the assignment in the constructor by an initialisation. This is a general best practice.)
It is not a good idea to return
return tmp.c_str();
because tmp.c_str() return a pointer to a memory location which will be freed after returning from the function.