Catching all unhandled C++ exceptions? - c++

Is there some way to catch exceptions which are otherwise unhandled (including those thrown outside the catch block)?
I'm not really concerned about all the normal cleanup stuff done with exceptions, just that I can catch it, write it to log/notify the user and exit the program, since the exceptions in these casese are generaly fatal, unrecoverable errors.
something like:
global_catch()
{
MessageBox(NULL,L"Fatal Error", L"A fatal error has occured. Sorry for any inconvience", MB_ICONERROR);
exit(-1);
}
global_catch(Exception *except)
{
MessageBox(NULL,L"Fatal Error", except->ToString(), MB_ICONERROR);
exit(-1);
}

This can be used to catch unexpected exceptions.
catch (...)
{
std::cout << "OMG! an unexpected exception has been caught" << std::endl;
}
Without a try catch block, I don't think you can catch exceptions, so structure your program so the exception thowing code is under the control of a try/catch.

Check out std::set_terminate()
Edit: Here's a full-fledged example with exception matching:
#include <iostream>
#include <exception>
#include <stdexcept>
struct FooException: std::runtime_error {
FooException(const std::string& what): std::runtime_error(what) {}
};
int main() {
std::set_terminate([]() {
try {
std::rethrow_exception(std::current_exception());
} catch (const FooException& e) {
std::cerr << "Unhandled FooException: " << e.what() << std::endl;
} catch (const std::exception& e) {
std::cerr << "Unhandled exception: " << e.what() << std::endl;
} catch (...) {
std::cerr << "Unhandled exception of unknown type" << std::endl;
}
std::abort();
});
throw FooException("Bad things have happened.");
// throw std::runtime_error("Bad things have happened.");
// throw 9001;
}

You can use SetUnhandledExceptionFilter on Windows, which will catch all unhandled SEH exceptions.
Generally this will be sufficient for all your problems as IIRC all the C++ exceptions are implemented as SEH.

Without any catch block, you won't catch any exceptions. You can have a catch(...) block in your main() (and its equivalent in each additional thread). In this catch block you can recover the exception details and you can do something about them, like logging and exit.
However, there are also downside about a general catch(...) block: the system finds that the exception has been handled by you, so it does not give any more help. On Unix/Linux, this help would constitute creating a CORE file, which you could load into the debugger and see the original location of the unexcepted exception. If you are handling it with catch(...) this information would be already lost.
On Windows, there are no CORE files, so I would suggest to have the catch(...) block. From that block, you would typically call a function to resurrect the actual exception:
std::string ResurrectException()
try {
throw;
} catch (const std::exception& e) {
return e.what();
} catch (your_custom_exception_type& e) {
return e.ToString();
} catch(...) {
return "Ünknown exception!";
}
}
int main() {
try {
// your code here
} catch(...) {
std::string message = ResurrectException();
std::cerr << "Fatal exception: " << message << "\n";
}
}

Update: This covers c++98 only.
From More Effective C++ by Meyers (pg 76), you could define a function that gets called when a function generates an exception that is not defined by its exception specification.
void convertUnexpected()
{
// You could redefine the exception here into a known exception
// throw UnexpectedException();
// ... or I suppose you could log an error and exit.
}
In your application register the function:
std::set_unexpected( convertUnexpected );
Your function convertUnexpected() will get called if a function generates an exception that is not defined by its exception specification... which means this only works if you are using exception specifications. ;(

Provided that C++11 is available, this approach may be used (see example from: http://en.cppreference.com/w/cpp/error/rethrow_exception):
#include <iostream>
#include <exception>
void onterminate() {
try {
auto unknown = std::current_exception();
if (unknown) {
std::rethrow_exception(unknown);
} else {
std::cerr << "normal termination" << std::endl;
}
} catch (const std::exception& e) { // for proper `std::` exceptions
std::cerr << "unexpected exception: " << e.what() << std::endl;
} catch (...) { // last resort for things like `throw 1;`
std::cerr << "unknown exception" << std::endl;
}
}
int main () {
std::set_terminate(onterminate); // set custom terminate handler
// code which may throw...
return 0;
}
This approach also allows you to customize console output for unhandled exceptions: to have something like this
unexpected exception: wrong input parameters
Aborted
instead of this:
terminate called after throwing an instance of 'std::logic_error'
what(): wrong input parameters
Aborted

This is what I always do in main()
int main()
{
try
{
// Do Work
}
catch(std::exception const& e)
{
Log(e.what());
// If you are feeling mad (not in main) you could rethrow!
}
catch(...)
{
Log("UNKNOWN EXCEPTION");
// If you are feeling mad (not in main) you could rethrow!
}
}

Use catch (...) in all of your exception barriers (not just the main thread). I suggest that you always rethrow (...) and redirect standard output/error to the log file, as you can't do meaningful RTTI on (...). OTOH, compiler like GCC will output a fairly detailed description about the unhandled exception: the type, the value of what() etc.

Related

Why does std::exception catch my exception before std::bad_alloc?

Problem : I am using both std::exception and std::bad_alloc to catch exception. Something is wrong with the order of the try catch that I am using. I attached sample code for reference.
Expected : If my error is bad_alloc then the bad_alloc exception is thrown.
Observed : My error is bad_alloc, but exception is thrown.
Sample Code :
#include "stdafx.h"
#include <iostream>
#include <exception>
using namespace std;
void goesWrong()
{
bool error1Detected = true;
bool error2Detected = false;
if (error1Detected)
{
throw bad_alloc();
}
if (error2Detected)
{
throw exception();
}
}
int main()
{
try
{
goesWrong();
}
catch (exception &e)
{
cout << "Catching exception: " << e.what() << endl;
}
catch (bad_alloc &e)
{
cout << "Catching bad_alloc: " << e.what() << endl;
}
return 0;
}
You have to put your exceptions in reverse order, regarding their inheritance relationship. std::exception is the parent class of std::bad_alloc, that is why it is found before in the catch list. So you have to transform your code to be:
try {
goesWrong();
}
catch (bad_alloc &e)
{
cout << "Catching bad_alloc: " << e.what() << endl;
}
catch (exception &e)
{
cout << "Catching exception: " << e.what() << endl;
}
You're not limited to catch objects: you can throw integers, chars... whatever. In that case, catch(...) is the only secure way to catch them all.
That said, using objects from the standard class library is the advised way to do it. And in this case, since std::exception is the base class for all (standard) exceptions, it will catch all possible exceptions thrown.
You can create your own exception classes deriving them from std::exception, or from std::runtime_error, for example, my personal choice.
Hope this helps.
In C++, the order in which exception handlers are listed is taken into account when matching handlers to exceptions. The first handler which can handle the exception will be called, even if there is a better match further down the list. This is different from Java or C#, where only the best match will be called (and the compiler forces you to put it at the top of the list).
As the exception is passed by reference, polymorphism applies; this means that a subclass can be passed to a handler that expects its parent class. Since std::bad_alloc is a subclass of std::exception, it will be handled by the first catch block.
To get the behaviour you expected, put the catch blocks the other way round:
catch (bad_alloc &e)
{
cout << "Catching bad_alloc: " << e.what() << endl;
}
catch (exception &e)
{
cout << "Catching exception: " << e.what() << endl;
}
This way round, std::bad_alloc will match the first handler, while std::exception and all its other subclasses will match the second.

In a C++ command-line application, how should I catch exceptions at the top-level?

I am writing a command-line application in C++. If an unhandled exception occurs, I don't want the app to crash badly, but to clean up as well as possible and print an error message.
How should I catch exceptions at the top-level in order to avoid the program crashing? Should I catch std::exception, ... or something else?
The quality of the cleaning you can do is a function of the exception being thrown.
For example, an exception that you raise yourself (perhaps derived from std::exception; let's call it fooexception) could well be handled quite elegantly.
So really you want a catch site on these lines
try {
/*whatever*/
} catch (fooexception& fe){
/*ToDo - handle my exception*/
} catch (std::exception& e){
/*ToDo - handle this generically*/
} catch (...){
/*Hum. That's bad. Let's do my best*/
}
Extend this at your leisure. Just remember that in a sense, multiple catch blocks behave like if else blocks: always order with the specific exceptions first.
Well, you could catch both:
int main() {
try {
// do stuff
}
catch(const std::exception& e) {
std::cout << "Caught exception: " << e.what() << std::endl;
}
catch(...) {
std::cout << "Caught unknown exception." << std::endl;
}
}
You should catch both, and possibly more. If you use a more specific exception type somewhere in the call stack, try to catch that as well.
Consider the code:
try
{
process();
}
catch (const SpecificException& ex)
{
std::cerr << "SpecificException occured: " << ex.what() << std::endl;
}
catch (const std::runtime_error& ex)
{
std::cerr << "std::runtime_error occured: " << ex.what() << std::endl;
}
catch (...)
{
std::cerr << "Unknown error occured!" << std::endl; // should never happen hopefully
}
And remember to always sort by specificness of exceptions - the more specialized/derived first, as the runtime will stop at the first catch block able to process the exception (i.e. first catch block with exception type matching or being a base of).

How to catch exceptions conditionally?

My large application has this structure:
int main()
{
try {
...
} catch (std::exception& e) {
std::cout << "Fatal error: " << e.what() << (some more data) << std::endl;
return 1;
}
}
Deep inside the call stack, various objects check their internal state, throwing std::runtime_exception if they detect something bad. The all-inclusive exception handler catches it, prints some moderately useful info and terminates the program.
However, when I am debugging under MS Visual Studio, I could benefit from not having any exception handler: Visual Studio has its own, very useful, handler, which stops my application at the place where the exception is thrown, so I can examine what went wrong.
How can I do the catching of my exceptions conditionally?
I tried the following:
try {
...
} catch (std::exception& e) {
if (IsDebuggerPresent())
throw;
else
std::cout << "Fatal error: " << e.what() << (some more data) << std::endl;
}
This gave a weird result: Visual Studio caught the exception that was rethrown and showed me the stack trace at the point where the exception was thrown. However, all objects in my application were apparently destructed, and I couldn't see e.g. local or member variables.
I could make the exception handler conditional on a compilation flag:
#ifdef NDEBUG
try {
#endif
...
#ifdef NDEBUG
} catch (std::exception& e) {
std::cout << "Fatal error: " << e.what() << (some more data) << std::endl;
}
#endif
but this is inconvenient because I have to recompile everything if I want to debug it.
So, how can I make my exception handling conditional (depending on a command-line argument, for example)?
So, how can I make my exception handling conditional (depending on a command-line argument, for example)?
By writing the code for it :o]
Consider this original code:
int main()
{
try {
run_the_application(); // this part different than your example
} catch (std::exception& e) {
std::cout << "Fatal error: " << e.what() << (some more data) << std::endl;
return 1;
}
}
New code:
template<typename F>
int fast_run(F functor) { functor(); return EXIT_SUCCESS; }
template<typename F>
int safe_run(F functor)
{
try {
functor();
} catch (std::exception& e) {
std::cout << "Fatal error: " << e.what() << (some more data) << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
template<typename F>
int run(const std::vector<std::string>& args, F functor)
{
using namespace std;
if(end(args) != find(begin(args), end(args), "/d"))
return fast_run(functor);
else
return safe_run(functor);
}
int main(int argc, char** argv)
{
const std::vector<std::string> args{ argv, argv + argc };
return run(args, run_the_application);
}
As suggested by CompuChip, Visual Studio can break execution when throwing an exception, not only when catching an uncaught one!
To enable this (in Visual Studio 2012):
In the menu, go Debug -> Exceptions
In the opened window, tick the "Thrown" box for all C++ exceptions (ticking just std::exception is not enough - I don't know why)
Run your program
This is something far from great but you can define command line parameter in CMake (assuming you use it):
-DCATCH_ALL=true
Then, in CMakelists.txt, you can propagate this to C++ macro:
if (CATCH_ALL)
message("Some exceptions with not be caught")
add_compile_definitions(CATCH_ALL)
else ()
message("Trying to catch more exceptions to provide better diagnostics")
endif ()
And finally, in the code:
#ifdef CATCH_ALL
try {
#endif
a = big_problematic_algorithm(problematic_parameter);
#ifdef CATCH_ALL
} catch (const std::exception &err) {
LOGF(WARN, "Crashed for the parameter %s: %s", problematic_parameter.c_str(), err.what());
}
#endif
It is rather clumsy but OK if not used too often, only somewhere at very high level (handling a complete web request, user action, file to process or the like). It allows to provide better diagnostic logs if the crash happens not while running in IDE, also to recover if you throw this exception yourself so know how.
It is possible to configure IDE to set the CMake parameter. When building on the integration server or from the command line, this is just not done activating additional handling of exceptions.

Why does my program crash from an exception even though I catch that exception type?

I have this code:
printf("hello\n");
try
{
for ( unsigned i = 0; i < par.size(); i++ )
rep.delete_rev(par[i]);
}
catch(TriedToDeleteRoot e)
{
printf("catched 1 !\n");
}
catch(...) {
printf("catched sth else !\n");
}
printf("hahaha\n");
and this is what i have on output:
hello
terminate called after throwing an instance of 'TriedToDeleteRoot'
what(): Tried to delete root
why? TriedToDeleteRoot inherits from std::exception, and I don't have any idea what's wrong. Thanks.
EDIT:
this is how I throw an exception:
throw TriedToDeleteRoot();
My guess is the copy constructor for TriedToDeleteRoot is failing.
I suggest (as always) catching by const reference:
try
{
for ( unsigned i = 0; i < par.size(); i++ )
rep.delete_rev(par[i]);
}
catch(const TriedToDeleteRoot& e)
{
printf("caught 1 !\n");
}
or in the general case:
catch(const std::exception& e)
{
std::cerr << "exception: " << e.what() << std::endl;
}
You're observing that std::terminate is being called even though you have a try/catch that you expect to match the exception that's being thrown.
One reason this might happen is if you've managed to throw an exception whilst a previous exception is being handled. You can observe this with:
#include <iostream>
int main() {
try {
struct test {
~test() { throw 0; }
} test;
throw 0;
}
catch (...) {
std::cout << "Caught something" << std::endl;
}
}
On my system this calls abort() and prints:
terminate called after throwing an instance of 'int'
Notice that the catch(...) never gets hit because of this.
This simple example illustrates the easiest way to accidentally make that happen - throwing from within a destructor. My best guess from what you've shown is that this is what's happening. A debugger ought to confirm this for you though.

c++: Catch runtime_error

I am learning c++ at home and I am using the rapidxml lib.
I am using the utils provided with it to open files:
rapidxml::file<char> myfile (&filechars[0]);
I noticed that if filechars is wrong the rapidxml::file throw a runtime_error:
// Open stream
basic_ifstream<Ch> stream(filename, ios::binary);
if (!stream)
throw runtime_error(string("cannot open file ") + filename);
stream.unsetf(ios::skipws);
I think I need to write something like that:
try
{
rapidxml::file<char> GpxFile (pcharfilename);
}
catch ???
{
???
}
I made some googling, but I did not find what I need in the place of the ???.
Could somebody help me?
Thanks!
You need to add an exception declaration next to the catch statement. The type thrown is std::runtime_error.
try
{
rapidxml::file<char> GpxFile (pcharfilename);
}
catch (const runtime_error& error)
{
// your error handling code here
}
If you need to catch multiple, different kinds of exceptions, then you can tack on more than one catch statement:
try
{
rapidxml::file<char> GpxFile (pcharfilename);
}
catch (const runtime_error& error)
{
// your error handling code here
}
catch (const std::out_of_range& another_error)
{
// different error handling code
}
catch (...)
{
// if an exception is thrown that is neither a runtime_error nor
// an out_of_range, then this block will execute
}
try
{
throw std::runtime_error("Hi");
}
catch(std::runtime_error& e)
{
cout << e.what() << "\n";
}
Well, it depends on what you want to do when it happens. This is the minimum:
try
{
rapidxml::file<char> GpxFile (pcharfilename);
}
catch (...)
{
cout << "Got an exception!"
}
If you want to get at the actual exception, then you need to declare a variable to store it in inside the parentheses in place of the three dots.