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);
Related
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.
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.
try
{
if (isfull()==1)
throw "full stack";
else
a[top++] = x;
}
catch (const char *s)
{
cout<<s;
}
Why should we use const in the catch block? If I don't use it, I get this error:
terminate called after throwing an instance of 'char const*'
Aborted (core dumped)
Because you are throwing a string literal, and a string literal is the same as a pointer to constant memory, hence the need for const.
More generally, it's because your catch block isn't catching the exception you're throwing, if you leave off the const.
However, throwing a non-exception type is considered bad form; consider throwing a std::runtime_error or other type derived from std::exception. You can construct most of them with a string, and get the message from the what() property.
You should still catch these by const reference, to prevent copying and modifying the caught object (which isn't a useful thing in any case):
try
{
throw runtime_error( "full stack" );
}
catch( const runtime_error & x )
{
cout << x.what();
}
catch( const exception & x )
{
// catch other exceptions derived from this base class.
}
Your try block throws a const type string: "full stack", which is not meant to be changed in your catch block.
In any case, const char * could not be implicitly casted to char *.
If the catch receive char *s parameter, the content that s point to might be changed by s[...] assignment, which is not acceptable, cause the content("full stack") is constant.
Because you can implicitly assign a variable of less qualifier to more qualifier
But you cant implicitly assign a variable of MORE qualifier to less qualifier
for example
foo(char * p)
fooc(const char * p)
int main(int argc, char agrv[]) {
const char* cp = "hello";
char* p = new char[10];
foo(cp); // ==> compilation error
strcpy(p, cp);
fooc(p) // No probs assigning to a more qualified var
}
Thats why #Joachim Pileborg is right :)
It's not so simple. The question is showing something in C++.
we can assign "const char*" literal to "char*"
char* ss = "full stack"; //ok, although "full stack" looks like a const char*
const char* s2 = "full stack";
char* ss = s2 ; //not ok
for take care of C program, C++ allow : char* ss = "full stack";
by the way. In my VS2005 complier, nothing happend( no coredump).
void main(){
try
{
throw "full stack";
}
catch (char *s)
{
std::cout << s <<std::endl;
}
}
I'm providing a c++ wrapper to the thread safe strerror_r in code like this:
struct MyErrno {};
std::ostream& operator<<(std::stream& os, const MyErrno& err)
{
const int len = 128
char buf [len];
os << strerror_r(errno, buf, len);
return os;
}
This is just a simple wrapper so in C++ code I can say something like
<< MyErrno() << ..
and use the threadsafe printing of the errno. It also seems to be ok to use 128 becuase the man page says strerror_r will either return a pointer to an immutable static string (presumably null terminated) or a pointer to buf after filling it in with a null terminator regardless of size...just not sure if there's something wrong with this simple wrapper (potentially buggy)
I don't understand the complete context in which you want to use this (in particular, what is the role of struct MyErrno, and what is StreamErrno, since your operator<< definition applies to a value of type sockaddr_in which isn't used).
However, in general terms, this is not a safe way to use errno, although it's a perfectly safe way to use strerror_r.
The problem is that you are mostly likely using this in a context like this:
if ((something) != OK) {
std::cerr << "Something bad happened: "
<< (some value which causes your function to be called)
<< ...
}
That is, there will probably be some system call (outputting the string "Something bad happened") between the system call which failed, leaving a value in errno, and the use of errno in your function. Pretty well any system call can cause errno to be set, even if the error is harmless; consequently, best practice is to grab the value of errno immediately. This would be a good reason to use a custom type like MyError:
struct MyError {
int error;
MyError(int err) : error(err) {}
};
std::ostream& operator<<(std::ostream& os, const MyError& e) {
// as with your function, but using `e.error` instead of `errno`
}
if ((something) != OK) {
MyError e(errno);
std::cerr << "Something bad happened: " << e
<< ...
}
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.