I have a very poor understanding of exception handling(i.e., how to customize throw, try, catch statements for my own purposes).
For example, I have defined a function as follows: int compare(int a, int b){...}
I'd like the function to throw an exception with some message when either a or b is negative.
How should I approach this in the definition of the function?
Simple:
#include <stdexcept>
int compare( int a, int b ) {
if ( a < 0 || b < 0 ) {
throw std::invalid_argument( "received negative value" );
}
}
The Standard Library comes with a nice collection of built-in exception objects you can throw. Keep in mind that you should always throw by value and catch by reference:
try {
compare( -1, 3 );
}
catch( const std::invalid_argument& e ) {
// do stuff with exception...
}
You can have multiple catch() statements after each try, so you can handle different exception types separately if you want.
You can also re-throw exceptions:
catch( const std::invalid_argument& e ) {
// do something
// let someone higher up the call stack handle it if they want
throw;
}
And to catch exceptions regardless of type:
catch( ... ) { };
Though this question is rather old and has already been answered, I just want to add a note on how to do proper exception handling in C++11:
Use std::nested_exception and std::throw_with_nested
It is described on StackOverflow here and here, how you can get a backtrace on your exceptions inside your code without need for a debugger or cumbersome logging, by simply writing a proper exception handler which will rethrow nested exceptions.
Since you can do this with any derived exception class, you can add a lot of information to such a backtrace!
You may also take a look at my MWE on GitHub, where a backtrace would look something like this:
Library API: Exception caught in function 'api_function'
Backtrace:
~/Git/mwe-cpp-exception/src/detail/Library.cpp:17 : library_function failed
~/Git/mwe-cpp-exception/src/detail/Library.cpp:13 : could not open file "nonexistent.txt"
Just add throw where needed, and try block to the caller that handles the error. By convention you should only throw things that derive from std::exception, so include <stdexcept> first.
int compare(int a, int b) {
if (a < 0 || b < 0) {
throw std::invalid_argument("a or b negative");
}
}
void foo() {
try {
compare(-1, 0);
} catch (const std::invalid_argument& e) {
// ...
}
}
Also, look into Boost.Exception.
You could define a message to throw when a certain error occurs:
throw std::invalid_argument( "received negative value" );
or you could define it like this:
std::runtime_error greatScott("Great Scott!");
double getEnergySync(int year) {
if (year == 1955 || year == 1885) throw greatScott;
return 1.21e9;
}
Typically, you would have a try ... catch block like this:
try {
// do something that causes an exception
}catch (std::exception& e){ std::cerr << "exception: " << e.what() << std::endl; }
Adding to this answer, as it doesn't seem advantageous to create another answer for this Q&A at this time.
In the case where you create your own custom exception, that derives from std::exception, when you catch "all possible" exceptions types, you should always start the catch clauses with the "most derived" exception type that may be caught. See the example (of what NOT to do):
#include <iostream>
#include <string>
using namespace std;
class MyException : public exception
{
public:
MyException(const string& msg) : m_msg(msg)
{
cout << "MyException::MyException - set m_msg to:" << m_msg << endl;
}
~MyException()
{
cout << "MyException::~MyException" << endl;
}
virtual const char* what() const throw ()
{
cout << "MyException::what" << endl;
return m_msg.c_str();
}
const string m_msg;
};
void throwDerivedException()
{
cout << "throwDerivedException - thrown a derived exception" << endl;
string execptionMessage("MyException thrown");
throw (MyException(execptionMessage));
}
void illustrateDerivedExceptionCatch()
{
cout << "illustrateDerivedExceptionsCatch - start" << endl;
try
{
throwDerivedException();
}
catch (const exception& e)
{
cout << "illustrateDerivedExceptionsCatch - caught an std::exception, e.what:" << e.what() << endl;
// some additional code due to the fact that std::exception was thrown...
}
catch(const MyException& e)
{
cout << "illustrateDerivedExceptionsCatch - caught an MyException, e.what::" << e.what() << endl;
// some additional code due to the fact that MyException was thrown...
}
cout << "illustrateDerivedExceptionsCatch - end" << endl;
}
int main(int argc, char** argv)
{
cout << "main - start" << endl;
illustrateDerivedExceptionCatch();
cout << "main - end" << endl;
return 0;
}
NOTE:
The proper order should be vice-versa, i.e.- first you catch (const MyException& e) which is followed by catch (const std::exception& e).
As you can see, when you run the program as is, the first catch clause will be executed (which is probably what you did NOT want in the first place).
Even though the type caught in the first catch clause is of type std::exception, the "proper" version of what() will be called - cause it is caught by reference (change at least the caught argument std::exception type to be by value - and you will experience the "object slicing" phenomena in action).
In case that the "some code due to the fact that XXX exception was thrown..." does important stuff WITH RESPECT to the exception type, there is misbehavior of your code here.
This is also relevant if the caught objects were "normal" object like: class Base{}; and class Derived : public Base {}...
g++ 7.3.0 on Ubuntu 18.04.1 produces a warning that indicates the mentioned issue:
In function ‘void illustrateDerivedExceptionCatch()’:
item12Linux.cpp:48:2: warning: exception of type ‘MyException’ will be caught
catch(const MyException& e)
^~~~~
item12Linux.cpp:43:2: warning: by earlier handler for ‘std::exception’
catch (const exception& e)
^~~~~
Again, I will say, that this answer is only to ADD to the other answers described here (I thought this point is worth mentioning, yet could not depict it within a comment).
Related
I am learning C++ and I am experiencing when I try and create my own exception and throw them on Linux.
I've created a small test project to test my implementation and below is my exception class header file.
class TestClass : public std::runtime_error
{
public:
TestClass(char const* const message) throw();
virtual char const* what() const throw();
};
The source file for the exception class is
using namespace std;
TestClass::TestClass(char const* const message) throw()
: std::runtime_error(message)
{
}
char const * TestClass::what() const throw()
{
return exception::what();
}
In my main app, I am calling a function which throws my exception and catches it in a try/catch as follows:
void runAFunctionAndthrow();
/*
*
*/
int main(int argc, char** argv) {
try
{
cout << "About to call function" << endl;
runAFunctionAndthrow();
}
catch (TestClass ex)
{
cout << "Exception Caught: " << ex.what() << endl;
}
return 0;
}
void runAFunctionAndthrow()
{
cout << "going to run now. oh dear I need to throw an exception" << endl;
stringstream logstream;
logstream << "This is my exception error. :(";
throw TestClass(logstream.str().c_str());
}
When I run I'm expecting to get the following output:
About to call function
Going to run now. oh dear I need to throw an exception
Exception Caught: This is my exception error. :(
Instead what I am getting is
About to call function
going to run now. oh dear I need to throw an exception
Exception Caught: std::exception
Notice the last line it says std::exception instead of my actual exception message "This is my exception error".
Why is this, it works OK on Windows but on Linux it does this.
From what I've seen on various posts what I've done is correct so what am I missing.
Your what() returns:
return exception::what();
The return value from std::exception::what() is specified as follows:
Pointer to a null-terminated string with explanatory information.
That's it. Nothing more, nothing else. The text you're showing certainly qualifies as an "explanatory information". And this is the only requirement for the return value of what() (except for one other one which is not germane here).
In other words, C++ does not guarantee the exact contents of what you get with what(). what() you see is what() you get, as the saying goes.
If you want your exception to describe itself, in some way, it's up to you to implement that, as part of your what().
You need your own implementation of what() method or use std::runtime_error::what() as written in comments
Say:
class TestClass : public std::runtime_error
{
std::string what_message;
public:
const char* what() override
{
return what_message.c_str();
}
};
Also, better use noexcept instead of throw() and only after you read about them - link.
And in your try-catch:
catch (const TestClass& myException)
Instead of catch(TestClass myException) - otherwise you do an implicit copy which can potentially result in an exception throw. It also breaks the polymorphism: if you want to catch pure virtual interface implementation instance, you would need to use a reference.
You need a way to specify a custom error message to std::exception which afaik is not allowed. See this for a possible solution.
First of most of the info about the answer had been given by Sam Varshavchik
But I want to add one thing
When throwing and catching A good rule is
"Throw by value catch by reference "
So your throw was fine as:
void runAFunctionAndthrow()
{
cout << "going to run now. oh dear I need to throw an exception" << endl;
stringstream logstream;
logstream << "This is my exception error. :(";
throw **TestClass(logstream.str().c_str())**;
}
used an implicit conversion to TestClass and then it got passed by value.
the Key point in that rule is to minimize memory allocating handling between different stack frames
your catch on the other hand dosen't follow the rule (since you catch by value):
catch (TestClass ex)
{
cout << "Exception Caught: " << ex.what() << endl;
}
the catch should be (const TestClass& ex)
the key point in this rule is implicit conversion between base class and derived class.
I am writing a program in C++ which handles errors via throwing strings (either std::string or const char*), like so :
if (/* failure condition 1 */)
throw std::string("Error 1 : ...") + std::to_string(foo);
if (/* failure condition 2 */)
throw "Error 2 : ...";
Then I would catch them this way :
try {
thisIsLikelyToThrowErrors();
} catch (const std::string& e) {
std::cerr << ":( " << e << std::endl;
} catch (const char* e) {
std::cerr << ":( " << e << std::endl;
}
I would like to avoid writing the same line twice, by forwarding the string from the first catch block to the second one :
try {
thisIsLikelyToThrowErrors();
} catch (const std::string& e) {
throw e.c_str(); // Does not work
} catch (const char* e) {
std::cerr << ":( " << e << std::endl;
}
However this code won't work, the thrown char const* simply won't be catched.
Is there a way to do this?
Thanks :)
No, you cannot do this.
[C++14: 15.1/1]: When an exception is thrown, control is transferred to the nearest handler with a matching type (15.3); “nearest” means the handler for which the compound-statement or ctor-initializer following the try keyword was most recently entered by the thread of control and not yet exited.
You would have to nest entire try/catch pairs:
try {
try {
thisIsLikelyToThrowErrors();
}
catch (const std::string& e) {
throw e.c_str(); // Does not work
}
}
catch (const char* e) {
std::cerr << ":( " << e << std::endl;
}
Ew!
But now you have another problem, in that the std::string e dies after you've thrown its C-string buffer (it'd stay alive if you re-threw it). Probably try to avoid this in general, eh?
Throw actual exceptions, instead.
You can handle the common setup in an independent function externally, calling it from your catches clauses.
In your example, you can do:
inline void HandleStringyException(const char* excStr)
{
//do something
}
Then:
try {
thisIsLikelyToThrowErrors();
} catch (const std::string& e) {
HandleStringyException(e.c_str());
} catch (const char* e) {
HandleStringyException(e);
}
P.S. It should be mentioned that exceptions are better to be handled polymorphically, and in order to do so, the objects thrown should be chosen wisely. As mentioned by others, throwing objects like strings and pointers is a bad practice, and generally you'd like to throw objects derived from std::exception. Sometimes, however, the throwing code is not under your control and you have to make the best of it. I think that's a different discussion.
There is a simple solution to your actual problem:
Throw only std::string or only const char*.
Or even better throw something derived from std::exception
I wrote a routine to store the backtrace and line no and file name etcetera. The purpose for this was to store such data for whenever an exception is thrown. However, the problem I am facing is that my routine will be called from the catch block and it will end up storing the backtrace up to the catch block. This is not good. I only must add the backtrace till the place where the exception is thrown. I cannot (obviously call it inside the try block since in that case I will end up storing a backtrace even in the cases where no exception is thrown). I could also always store the backtrace to the end of the try block and access it inside the catch block; but there is no way of knowing at which line of the try block the exception will be thrown. Thus the throw function seems to be a good place to add the routine call. But I dont know how to do it. Please help me.
If my strategy seems inherently wrong, please feel free to point me a better solution. If the problem itself is not clear, please leave a comment.
P.S. I wrote the custom exception class to inherit from std::runtime_error.
There is no 'throw function' defined by C++ that you can override. Throwing is handled by the C++ implementation and there's no standard way to insert any kind of code for every throw.
Instead what you can do is make your exception type store the current backtrace when it is constructed.
std::string get_backtrace() {
return "this is the backtrace...";
}
struct backtrace_exception : public std::exception {
std::string b;
backtrace_exception() : b(get_backtrace()) {}
};
int main() {
try {
throw backtrace_exception();
} catch(backtrace_exception &e) {
std::cout << e.b;
}
}
You cannot overload the throw operator. The more usual solution would be to define a macro that packages the exception with a backtrace record. For example this:
#include <string>
#include <iostream>
#include <sstream>
#include <exception>
#include <stdexcept>
#include <type_traits>
template <typename BaseException>
class backtraced_exception : public BaseException {
private:
std::string backtrace;
public:
template <typename... Args>
backtraced_exception(const char* aFilename, int aLineNum, Args&&... args) :
BaseException(std::forward<Args>(args)...) {
std::stringstream ss;
ss << "From '" << aFilename << "' at line " << aLineNum << ":\n"
<< BaseException::what();
backtrace = ss.str();
};
backtraced_exception(const std::exception& e, const char* aFilename, int aLineNum) :
BaseException(static_cast<const BaseException&>(e)) {
std::stringstream ss;
ss << "From '" << aFilename << "' at line " << aLineNum << ":\n"
<< e.what();
backtrace = ss.str();
};
virtual ~backtraced_exception() noexcept { };
virtual const char* what() const noexcept {
return backtrace.c_str();
};
};
#define THROW_WITH_BACKTRACE(EXCEPTION, ARG1) throw backtraced_exception< EXCEPTION >(__FILE__, __LINE__, ARG1)
// ... and you can create more macros for more arguments...
#define CATCH_WITH_BACKTRACE(EXCEPTION, EXCEPT_NAME) catch(backtraced_exception< EXCEPTION >& EXCEPT_NAME)
#define RETHROW_WITH_BACKTRACE(EXCEPT_NAME) throw backtraced_exception< std::decay< decltype(EXCEPT_NAME) >::type >(EXCEPT_NAME, __FILE__, __LINE__)
Use it like this:
int main() {
try {
try {
try {
THROW_WITH_BACKTRACE(std::runtime_error, "This is an example!");
} CATCH_WITH_BACKTRACE(std::runtime_error, e) {
std::cout << "First caught this exception:\n" << e.what() << std::endl;
RETHROW_WITH_BACKTRACE(e);
};
} catch(std::runtime_error& e) { // can also catch normally.
std::cout << "Got this exception:\n"
<< e.what() << std::endl;
// and even rethrow again, with backtrace:
RETHROW_WITH_BACKTRACE(e);
};
} catch(std::runtime_error& e) {
std::cout << "Finally, got this exception:\n"
<< e.what() << std::endl;
};
};
The output is as follows:
First caught this exception:
From 'logged_except.cpp' at line 50:
This is an example!
Got this exception:
From 'logged_except.cpp' at line 53:
From 'logged_except.cpp' at line 50:
This is an example!
Finally, got this exception:
From 'logged_except.cpp' at line 59:
From 'logged_except.cpp' at line 53:
From 'logged_except.cpp' at line 50:
This is an example!
Another good thing with this solution is that you can disable backtracing by simply conditionally defining the macros depending on whether you want backtracing or not (e.g. debug or release build).
The above example requires C++11 features, but you can probably come up with an equivalent solution without those features (i.e., variadic templates, decltype, type-traits, etc.).
And you could also use C++11 exception-pointers to make this scheme even more convenient.
Yeah you can override 'throw' under GCC by overriding this function :
extern "C"
void __cxa_throw (void *thrown_exception, void *pvtinfo, void (*dest)(void *))
After doing your stuff you should call the real 'throw' for that you should use 'dlsym()' under Unix to get its address or use function wrapping under 'mingw' by passing -WL,-wrap,symbole to the linker , like in here GNU gcc/ld - wrapping a call to symbol with caller and callee defined in the same object file , I worked with both methods
I have a very poor understanding of exception handling(i.e., how to customize throw, try, catch statements for my own purposes).
For example, I have defined a function as follows: int compare(int a, int b){...}
I'd like the function to throw an exception with some message when either a or b is negative.
How should I approach this in the definition of the function?
Simple:
#include <stdexcept>
int compare( int a, int b ) {
if ( a < 0 || b < 0 ) {
throw std::invalid_argument( "received negative value" );
}
}
The Standard Library comes with a nice collection of built-in exception objects you can throw. Keep in mind that you should always throw by value and catch by reference:
try {
compare( -1, 3 );
}
catch( const std::invalid_argument& e ) {
// do stuff with exception...
}
You can have multiple catch() statements after each try, so you can handle different exception types separately if you want.
You can also re-throw exceptions:
catch( const std::invalid_argument& e ) {
// do something
// let someone higher up the call stack handle it if they want
throw;
}
And to catch exceptions regardless of type:
catch( ... ) { };
Though this question is rather old and has already been answered, I just want to add a note on how to do proper exception handling in C++11:
Use std::nested_exception and std::throw_with_nested
It is described on StackOverflow here and here, how you can get a backtrace on your exceptions inside your code without need for a debugger or cumbersome logging, by simply writing a proper exception handler which will rethrow nested exceptions.
Since you can do this with any derived exception class, you can add a lot of information to such a backtrace!
You may also take a look at my MWE on GitHub, where a backtrace would look something like this:
Library API: Exception caught in function 'api_function'
Backtrace:
~/Git/mwe-cpp-exception/src/detail/Library.cpp:17 : library_function failed
~/Git/mwe-cpp-exception/src/detail/Library.cpp:13 : could not open file "nonexistent.txt"
Just add throw where needed, and try block to the caller that handles the error. By convention you should only throw things that derive from std::exception, so include <stdexcept> first.
int compare(int a, int b) {
if (a < 0 || b < 0) {
throw std::invalid_argument("a or b negative");
}
}
void foo() {
try {
compare(-1, 0);
} catch (const std::invalid_argument& e) {
// ...
}
}
Also, look into Boost.Exception.
You could define a message to throw when a certain error occurs:
throw std::invalid_argument( "received negative value" );
or you could define it like this:
std::runtime_error greatScott("Great Scott!");
double getEnergySync(int year) {
if (year == 1955 || year == 1885) throw greatScott;
return 1.21e9;
}
Typically, you would have a try ... catch block like this:
try {
// do something that causes an exception
}catch (std::exception& e){ std::cerr << "exception: " << e.what() << std::endl; }
Adding to this answer, as it doesn't seem advantageous to create another answer for this Q&A at this time.
In the case where you create your own custom exception, that derives from std::exception, when you catch "all possible" exceptions types, you should always start the catch clauses with the "most derived" exception type that may be caught. See the example (of what NOT to do):
#include <iostream>
#include <string>
using namespace std;
class MyException : public exception
{
public:
MyException(const string& msg) : m_msg(msg)
{
cout << "MyException::MyException - set m_msg to:" << m_msg << endl;
}
~MyException()
{
cout << "MyException::~MyException" << endl;
}
virtual const char* what() const throw ()
{
cout << "MyException::what" << endl;
return m_msg.c_str();
}
const string m_msg;
};
void throwDerivedException()
{
cout << "throwDerivedException - thrown a derived exception" << endl;
string execptionMessage("MyException thrown");
throw (MyException(execptionMessage));
}
void illustrateDerivedExceptionCatch()
{
cout << "illustrateDerivedExceptionsCatch - start" << endl;
try
{
throwDerivedException();
}
catch (const exception& e)
{
cout << "illustrateDerivedExceptionsCatch - caught an std::exception, e.what:" << e.what() << endl;
// some additional code due to the fact that std::exception was thrown...
}
catch(const MyException& e)
{
cout << "illustrateDerivedExceptionsCatch - caught an MyException, e.what::" << e.what() << endl;
// some additional code due to the fact that MyException was thrown...
}
cout << "illustrateDerivedExceptionsCatch - end" << endl;
}
int main(int argc, char** argv)
{
cout << "main - start" << endl;
illustrateDerivedExceptionCatch();
cout << "main - end" << endl;
return 0;
}
NOTE:
The proper order should be vice-versa, i.e.- first you catch (const MyException& e) which is followed by catch (const std::exception& e).
As you can see, when you run the program as is, the first catch clause will be executed (which is probably what you did NOT want in the first place).
Even though the type caught in the first catch clause is of type std::exception, the "proper" version of what() will be called - cause it is caught by reference (change at least the caught argument std::exception type to be by value - and you will experience the "object slicing" phenomena in action).
In case that the "some code due to the fact that XXX exception was thrown..." does important stuff WITH RESPECT to the exception type, there is misbehavior of your code here.
This is also relevant if the caught objects were "normal" object like: class Base{}; and class Derived : public Base {}...
g++ 7.3.0 on Ubuntu 18.04.1 produces a warning that indicates the mentioned issue:
In function ‘void illustrateDerivedExceptionCatch()’:
item12Linux.cpp:48:2: warning: exception of type ‘MyException’ will be caught
catch(const MyException& e)
^~~~~
item12Linux.cpp:43:2: warning: by earlier handler for ‘std::exception’
catch (const exception& e)
^~~~~
Again, I will say, that this answer is only to ADD to the other answers described here (I thought this point is worth mentioning, yet could not depict it within a comment).
can I get description of an exception caught by
catch(...)
block? something like .what() of std::exception.
There is one trick you might be able to use:
catch(...) {
handle_exception();
}
void handle_exception() {
try {
throw;
} catch (const std::exception &e) {
std::cout << e.what() << "\n";
} catch (const int i) {
std::cout << i << "\n";
} catch (const long l) {
std::cout << l << "\n";
} catch (const char *p) {
std::cout << p << "\n";
} catch (...) {
std::cout << "nope, sorry, I really have no clue what that is\n";
}
}
and so on, for as many different types as you think might be thrown. If you really know nothing about what might be thrown then even that second-to-last one is wrong, because somebody might throw a char* that doesn't point to a nul-terminated string.
It's generally a bad idea to throw anything that isn't a std::exception or derived class. The reason std::exception exists is to allow everybody to throw and catch objects that they can do something useful with. In a toy program where you just want to get out of there and can't even be bothered to include a standard header, OK, maybe throw an int or a string literal. I don't think I'd make that part of a formal interface. Any exceptions you throw are part of your formal interface, even if you somehow forgot to document them.
That block might catch an int, or a const char*, or anything. How can the compiler possibly know how to describe something when it knows nothing about it? If you want to get information off an exception, you must know the type.
If you know you only throw std::exception or subclasses, try
catch(std::exception& e) {...e.what()... }
Otherwise, as DeadMG wrote, since you can throw (almost) everything, you cannot assume anything about what you caught.
Normally catch(...) should only be used as the last defense when using badly written or documented external libraries. So you would use an hierarchy
catch(my::specialException& e) {
// I know what happened and can handle it
... handle special case
}
catch(my::otherSpecialException& e) {
// I know what happened and can handle it
... handle other special case
}
catch(std::exception& e) {
//I can at least do something with it
logger.out(e.what());
}
catch(...) {
// something happened that should not have
logger.out("oops");
}
Since C++11 you can capture the current exception with a pointer:
std::exception_ptr p; // default initialization is to nullptr
try {
throw 7;
}
catch(...)
{
p = std::current_exception();
}
This behaves like a smart pointer; so long as there is at least one pointer pointing to the exception object it is not destroyed.
Later (maybe even in a different function) you can take action in a similar way to the current top answer:
try {
if ( p )
std::rethrow_exception(p);
}
catch(int x)
{
}
catch(std::exception &y)
{
}
How we have our exceptions implemented is that, we have our own Exception classes, that are all derived from std::exception..
Our exceptions will contain Exception message, Function name, File name and line where exceptions are generated. These are all useful not just to show the Messages but also can be used for logging which helps to diagnose the Exception quite easily. So, we get the entire information about the Exceptions generated.
Remember exceptions are for us to get information about what went wrong. So, every bit of information helps in this regard..
Quoting bobah
#include <iostream>
#include <exception>
#include <typeinfo>
#include <stdexcept>
int main()
{
try {
throw ...; // throw something
}
catch(...)
{
std::exception_ptr p = std::current_exception();
std::clog <<(p ? p.__cxa_exception_type()->name() : "null") << std::endl;
}
return 1;
}