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.
Related
I am a C++ beginner and I am writing a class in C++ and I am using std::string.
How do I handle bad_alloc exception?
Can I do:
Temp::Temp(const string name) :
{
try {
name(name);
}
catch(std::bad_alloc& a) {
cout << "bad alloc error" << endl;
}
}
or should I do
Temp::Temp(const string name) :
name(name)
{
catch(std::bad_alloc& a) {
cout << "bad alloc error" << endl;
}
}
I want to catch the exception so that I would be able to prevent memory leak, and then maybe throw it again.
Also when I use x.assaing(y) from std::string do I have to check for bad_alloc exception too? (If I want to handle memory leaks.)
I am looking for a way without smart pointers (we didn't learn it yet).
Initializing a member of type std::string via constructor in a member initializer list won't cause memory leak.
#include <string>
struct Temp
{
Temp (const std::string& name): name(name) {}
std::string name;
};
Temp t ("yourname");
std::cout << t.name; // yourname
UPDATE: (suggested by #Deduplicator)
If only using one ctor, might as well use std::string_view which is a:
constant contiguous sequence of char-like objects
Like:
#include <string_view>
struct Temp
{
Temp (std::string_view name): name(name) {}
std::string name;
};
Temp t ("yourname");
std::cout << t.name; // yourname
If string construction does throw bad_alloc there is very little you can do to recover from it. You certainly should not be wrapping each construction of a string in a try-block. Instead you should allow the exception to bubble up to a higher level, such as your main function, catch it there, report the error somehow, and probably terminate the program. In general, you want to catch exceptions at the highest possible level that they can sensibly be handled.
This question is similar to c++ Exception Class Design and follows:
I want to design exception class hierarchy for my application and here are the design points I used:
Exception should be derived from standard exception classes (those are std::exception, std::logic_error and std::runtime_error).
Exception class should be able to take error description (i.e. what is called what) and position where it occurred (const std::string &file, int line)
Exception should not throw any exception during construction or from any other member.
Given this I have:
#define throw_line(TException, what) throw TException((what), __FILE__, __LINE__)
class AnException : public std::exception {
public:
AnException(const std::string &what, const std::string &file, int line) noexcept {
try {
what_ = what;
file_ = file;
line_ = line;
} catch (std::exception &e) {
was_exception_ = true;
}
}
virtual ~AnException() noexcept {}
virtual const char *what() const noexcept override {
if (was_exception_) {
return "Exception occurred while construct this exception. No further information is available."
} else {
try {
std::string message = what_ + " at " + file_ + ":" + std::to_string(line);
return message.c_str();
} catch (std::exception &e) {
return "Exception occurred while construct this exception. No further information is available."
}
}
}
};
class ParticularException : public AnException {
...
}
As you can see, it appears to be somewhat complex to construct such class, because we definitely should not have exceptions in constructor (otherwise std::terminate() will be called) or in what() member.
The question: is this example of a good design or I should remove some restrictions (like, having file/line information) to simplify it? Is there a better way?
I'm free to use C++11/C++14, but trying to keep off C++17 since it is not yet finished and compilers may not fully implement it.
Note: I want this code to be cross-platform.
Thanks in advance.
Edit 1: The follow up question: how can I retire file/line information, but keep that in logs? May be printing stacktrace is a better solution than what I have now? I mean leave exception class which just holds an error message (what) and call something like print_backtrace on upper level of exception handling chain.
Relating to my comment, depending on whether a what literal is acceptable, I had something like this in mind:
#include <array>
template <int N> constexpr std::size_t arraySize(const char (&)[N]){return N;}
template <class ExceptT, std::size_t whatN, std::size_t fileN>
class MyExcept : public ExceptT
{
static_assert(std::is_base_of<std::exception, ExceptT>::value, "bad not base");
public:
MyExcept(
const char (&what)[whatN],
const char (&file)[fileN],
int line) noexcept
: ExceptT(""), //Using our own what
what_(), file_(), line_(line)
{
std::copy(std::begin(what), std::end(what), begin(what_));
std::copy(std::begin(file), std::end(file), begin(file_));
}
virtual const char *what() const noexcept override
{
//....
}
private:
std::array<char,whatN> what_;
std::array<char,fileN> file_;
int line_;
};
#define throw_line(TException, what) throw MyExcept<TException,arraySize(what),arraySize(__FILE__)>(what,__FILE__, __LINE__)
void driver()
{
throw_line(std::runtime_error, "Hoo hah");
}
I've added some code that allows deriving from a std::exception type (type requires constructor with single literal argument (could check that this is also noexcept). I'm passing it an empty string literal, so std::exception class should at least not throw. I'm using static_assert to check this.
it cannot throw on construction...
it derives from std::exception...
it contains "fixed" what and position
This usually happens only, if you want to catch certain errors in another catch-block than your most outer catch block. I would only start doing this, if I see a demand. I remember that my system-call-read() wrapper would throw a different exception for EOF -- since this sometimes need to be caught.
Then I've got a system-error-exception and a normal message exception, since std::exception does not store any message with certain compilers.
Separate classes for exceptions are overused in the same way throw-specifications were overused.
Please remember that if you want to catch a certain error somewhere else than in the outer-most-catch-block, you need to be able to do something about the error, other than re-throw it. Usually the string returned from what() should already be sufficient to tell you what kind of error occurred. Thus for printing reasons there is no need to overload the exception type.
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.
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.
If a system call fails, I would like to throw an exception that contains the 'errno' relating to the failure. Right now, I use this:
if (bind(...) == -1) {
std::stringstream s;
s << "Error:" << errno << " during bind";
throw std::runtime_error(s.str());
}
That seems clumsy. I cannot directly append an integer to an std::string() - what is the best solution for this? Java has String().append(int), but there's no such facility in std::string. Does everyone write a wrapper around std::string for this purpose?
boost::lexical_cast is useful in this scenario:
throw std::runtime_error("Error:" + boost::lexical_cast<std::string>(errno) + " during bind");
I like using boost::format for this.
std::string msg = boost::str( boost::format("Error: %1% during bind") % errno );
throw std::runtime_error(msg);
One caveat is that if you have a bad_alloc in a catch block, you might hide the previous error. boost::format uses allocations as far as I know, so it could suffer from this. You aren't catching here, so it doesn't exactly apply. It is something to be aware of with error handling though.
You could write your own:
Here is some hints:
class Exception{
public:
Exception(const char* sourceFile, const char* sourceFunction, int sourceLine, Type type, const char* info = 0, ...);
protected:
const char *mSourceFile;
const char *mSourceFunction;
int mSourceLine;
Type mType;
char mInfo[2048];
};
Where type could be:
enum Type
{
UNSPECIFIED_ERROR, //! Error cause unspecified.
.. other types of error...
};
So you can pass string in the usual format.. e.g.
Exception(__FILE__, __FUNCTION__, __LINE__, Type::UNSPECIFIED_ERROR, "Error %d", myInt);