I want to set a global exception handler in C++. With a hook, any exceptions (of a specified type) thrown, would be caught by the handler. With this, I could do a little pretty printing before the exception kills the program, or maybe I could write everything to a log file.
boost seems to have an exception handler hook. This seemed extremely promising, but the code provided didn't work as I thought it should. Am I missing something?
struct my_handler
{
typedef void result_type;
void operator() (std::runtime_error const& e) const
{
std::cout << "std::runtime_error: " << e.what() << std::endl;
}
void operator() (std::logic_error const& e) const
{
std::cout << "std::logic_error: " << e.what() << std::endl;
throw;
}
};
void init_exception_handler()
{
// Setup a global exception handler that will call my_handler::operator()
// for the specified exception types
logging::core::get()->set_exception_handler(logging::make_exception_handler<
std::runtime_error,
std::logic_error
>(my_handler()));
}
// The above is all code from the boost doc example. Untouched.
int main(int argc, char* argv[]) {
init_exception_handler();
// I can throw now right...?
throw std::runtime_error("This should be suppressed!");
return 0;
}
In this code, the runtime_error I throw is not suppressed even though I thought I had setup the exception handler.
Related
This is about wrapping the exception handling logic in some sort of class. While writing c++
code, many time we need to catch many type/variants of exception depending on what client throw. This lead us to write similar types of code(many times) in catch() clause.
In below sample example, I have written the function(), which can throw exception in the many possible form.
I wanted to know is it possible to write/wrap such logic in the form of class so that end user would have to write similar types of code at once place?. Does it make any sense or it has any meaning?
#include<vector>
#include<string>
#include<exception>
#include<iostream>
// this function can throw std::exception, std::string, int or unhandled
void function() {
std::vector<int> x{1,2,3,4,5};
auto val = x.at(x.size()); //throw out-of-range error
}
int main() {
try { function(); }
catch(std::exception& e) { std::cout<<e.what()<<std::endl; }
catch(std::string& msg) { std::cout<<msg<<std::endl; }
catch(int i) { std::cout<<i<<std::endl; }
catch(...) { std::cout<<"Unhandled Exception"<<std::endl; }
return 0;
}
So far I thought in this way and below is the pseudo logic.
class exceptionwrapper{
exceptionwrapper(function pointer* fp) {
// functions which would be executing inside try
}
~exceptionwrapper() {
// all catch() clause can be written over here
// or some other member function of this class
}
};
The object of this class can be instantiated in the main() in this way.
int main() {
exceptionwrapper obj(function);
//here execptionwrapper destructor would take care about calling all type of catch
}
It is possible using std::exception_ptr:
Live demo link.
#include <iostream>
#include <exception>
#include <stdexcept>
void universal_exception_handler(std::exception_ptr e)
{
try
{
std::rethrow_exception(e);
}
catch (const std::logic_error& e)
{
std::cout << "logic_error" << std::endl;
}
catch (const std::runtime_error& e)
{
std::cout << "runtime_error" << std::endl;
}
}
void foo()
{
throw std::logic_error{""};
}
void bar()
{
throw std::runtime_error{""};
}
int main()
{
try
{
foo();
}
catch (...)
{
universal_exception_handler(std::current_exception());
}
try
{
bar();
}
catch (...)
{
universal_exception_handler(std::current_exception());
}
}
You can also achieve this without std::exception_ptr, just put throw; in place of std::rethrow_exception(e);, hoping this function will be invoked only if there is an active exception being handled (otherwise your program will be terminate()'ed):
void universal_exception_handler()
{
try
{
throw;
}
catch (const std::logic_error& e)
{
std::cout << "logic_error" << std::endl;
}
catch (const std::runtime_error& e)
{
std::cout << "runtime_error" << std::endl;
}
}
try
{
foo();
}
catch (...)
{
universal_exception_handler();
}
Yet another live demo link.
What you're asking for is possible, but I don't think it's very useful. First let's implement a mechanism to accept a callable object, and its associated arguments, which we'll invoke in the destructor of exception_wrapper.
template<typename Func, typename... Args>
struct exception_wrapper
{
exception_wrapper(Func f, Args... args)
: f_(std::move(f))
, args_(std::make_tuple(std::move(args)...))
{}
~exception_wrapper()
{
try {
invoke();
} catch(std::exception const& e) {
std::cerr << "Caught exception: " << e.what() << std::endl;
} catch(...) {
std::cerr << "Caught unknown exception" << std::endl;
}
}
template<std::size_t... I>
void apply(std::index_sequence<I...>)
{
f_(std::get<I>(args_)...);
}
void invoke()
{
apply(std::index_sequence_for<Args...>());
}
Func f_;
std::tuple<Args...> args_;
};
template<typename Func, typename... Args>
auto make_exception_wrapper(Func&& f, Args&&... args)
{
return exception_wrapper<Func, Args...>(
std::forward<Func>(f), std::forward<Args>(args)...);
}
This makes use of the C++14 std::integer_sequence; if that's not available on your implementation there are several answers on SO that show how to implement it yourself (this one for instance).
To use it, create an exception_wrapper object, and your function will be invoked when the destructor executes.
make_exception_wrapper(function);
Live demo
Now, I don't think this is useful because in general you should only catch exceptions if your code is able to handle them, and continue operating normally. Otherwise let them propagate to the top level where you might want to install a handler so it allows you to exit the program gracefully.
Given that, it's unlikely that there'll be a common approach to handling all exceptions thrown by your code, which greatly reduces the utility of exception_wrapper as implemented. You could modify it to take another callable argument, the exception handler that will be passed the std::exception object that was caught, which makes the class a little more generic.
Additionally, invoking the function in the destructor means you cannot pass the return value, if any, back to the caller. This can be fixed by invoking the function within exception_wrapper::operator() instead, but that then adds the wrinkle of what to return in the case an exception is indeed thrown, and you've suppressed it.
Finally, do not write code that throws types that are not derived from std::exception. This makes your code unidiomatic, and if you do want to handle the exception, you'll need to litter the code with several catch statements, like you have in your example.
I'm starting to use exceptions and to handle more precisely some events or errors, I created my own type of exceptions derived from std::exception. So far everything went well but I've just noticed that sometimes the method what() does not print anything. The exception is well thrown and caught, but the explanation message print normally by the method what() does not always show on screen. It can happen with the same parameters as the previous execution which ended printing the message and seems to be completely random.
Here's my exceptions :
class MyException : public std::exception
{
public:
MyException() throw() {}
~MyException() throw() {}
virtual const char *what() const throw()
{
return "general exception\n";
}
};
class FileError : public MyException
{
public:
FileError(std::string nFileName) : MyException(), fileName(nFileName) { }
~FileError() throw (){ }
virtual const char *what()
{
std::ostringstream oss;
oss << "Error with file : \"" << fileName << "\"." << std::endl;
return (oss.str()).c_str();
}
protected:
std::string fileName;
};
and the context which cause me problem :
try
{
QFile sourceFile(sourceFileName);
if(!sourceFile.open(QIODevice::ReadOnly))
throw FileError(sourceFileName.toStdString());
sourceFile.close();
}
catch(FileError &e)
{
std::cout << "error file catch " << std::endl;
std::cout << e.what();
terminate();
}
"error file catch" is always print but "Error with file..." sometimes. Any idea what I'm doing wrong ? Thanks
You are returning a pointer to the contents of a temporary std::string.
You aren't flushing std::cout prior to calling terminate (assuming that is std::terminate). I would recommend using std::endl (which is a newline and a flush) at the point where it's output, and not inside FileError::what()
catch(FileError &e)
{
std::cout << "error file catch " << std::endl;
std::cout << e.what() << std::endl;
terminate();
}
Also, as pointed out by #Yuri Kilocheck, you're returning a pointer to a temporary string, invoking UB. The usual solution is to have a string member that is built when what() is executed (if there is a failure building the string, return some pre-defined version).
I have a silly question. I read this article about std::exception http://www.cplusplus.com/doc/tutorial/exceptions/
On catch (exception& e), it says:
We have placed a handler that catches exception objects by reference (notice the ampersand & after the type), therefore this catches also classes derived from exception, like our myex object of class myexception.
Does this mean that by using "&" you can also catch exception of the parent class? I thought & is predefined in std::exception because it's better to pass e (std::exception) as reference than object.
The reason for using & with exceptions is not so much polymorphism as avoiding slicing. If you were to not use &, C++ would attempt to copy the thrown exception into a newly created std::exception, potentially losing information in the process. Example:
#include <stdexcept>
#include <iostream>
class my_exception : public std::exception {
virtual const char *what() const throw() {
return "Hello, world!";
}
};
int main() {
try {
throw my_exception();
} catch (std::exception e) {
std::cout << e.what() << std::endl;
}
return 0;
}
This will print the default message for std::exception (in my case, St9exception) rather than Hello, world!, because the original exception object was lost by slicing. If we change that to an &:
#include <stdexcept>
#include <iostream>
class my_exception : public std::exception {
virtual const char *what() const throw() {
return "Hello, world!";
}
};
int main() {
try {
throw my_exception();
} catch (std::exception &e) {
std::cout << e.what() << std::endl;
}
return 0;
}
Now we do see Hello, world!.
Does this mean that by using "&" you can also catch exception of the parent class?
No, this doesn't increase the scope of where you will catch exceptions from (e.g. from the parent class of the class that contains the try/catch code).
It also doesn't increase the types of exceptions that can be caught, compared to catching by value (catch(std::exception e) without the & - you'll still catch each exception that either is std::exception or derives from it).
What it increases is the amount of data that you will actually get when you catch the exception.
If an exception is thrown that derives from std::exception, and you catch it by value, then you are throwing out any extra behavior in that exception class. It breaks polymorphism on the exception class, because of Slicing.
An example:
class MyException : public std::exception
{
public:
virtual const char* what() const
{
return "hello, from my exception!";
}
};
// ...
try
{
throw MyException();
}
catch(std::exception& e)
{
// This will print "hello, from my exception!"
std::cout << e.what() << "\n";
}
// ...
try
{
throw MyException();
}
catch(std::exception e)
{
// This will print "Unknown exception"
std::cout << e.what() << "\n";
}
No the & has absolutely no bearing on the polymorphic nature of exception handlers. Their wording is very poor, it does seem to indicate that the & is somehow responsible. This is not the case. You are correct, & just passes by reference which is a tad more efficient.
Also as a general rule, you should really try to avoid cplusplus.com.
Updated link: What's wrong with cplusplus.com
Using reference to exception here can reduce the temporary objects created, and it can also keep the polymorphism.
There are some articles concluding "never throw an exception from a destructor", and "std::uncaught_exception() is not useful", for example:
http://www.gotw.ca/gotw/047.htm (written by Herb Sutter)
But it seems that I am not getting the point. So I wrote a small testing example (see below).
Since everything is fine with the testing example I would very appreciate some comments regarding what might be wrong with it ?
testing results:
./main
Foo::~Foo(): caught exception - but have pending exception - ignoring
int main(int, char**): caught exception: from int Foo::bar(int)
./main 1
Foo::~Foo(): caught exception - but *no* exception is pending - rethrowing
int main(int, char**): caught exception: from Foo::~Foo()
example:
// file main.cpp
// build with e.g. "make main"
// tested successfully on Ubuntu-Karmic with g++ v4.4.1
#include <iostream>
class Foo {
public:
int bar(int i) {
if (0 == i)
throw(std::string("from ") + __PRETTY_FUNCTION__);
else
return i+1;
}
~Foo() {
bool exc_pending=std::uncaught_exception();
try {
bar(0);
} catch (const std::string &e) {
// ensure that no new exception has been created in the meantime
if (std::uncaught_exception()) exc_pending = true;
if (exc_pending) {
std::cerr << __PRETTY_FUNCTION__
<< ": caught exception - but have pending exception - ignoring"
<< std::endl;
} else {
std::cerr << __PRETTY_FUNCTION__
<< ": caught exception - but *no* exception is pending - rethrowing"
<< std::endl;
throw(std::string("from ") + __PRETTY_FUNCTION__);
}
}
}
};
int main(int argc, char** argv) {
try {
Foo f;
// will throw an exception in Foo::bar() if no arguments given. Otherwise
// an exception from Foo::~Foo() is thrown.
f.bar(argc-1);
} catch (const std::string &e) {
std::cerr << __PRETTY_FUNCTION__ << ": caught exception: " << e << std::endl;
}
return 0;
}
ADDED: In other words: despite of the warnings in some articles it works as expected - so what might be wrong with it?
Herb Sutter is referring to a different issue. He's talking about:
try
{
}
catch (...)
{
try
{
// here, std::uncaught_exception() will return true
// but it is still safe to throw an exception because
// we have opened a new try block
}
catch (...)
{
}
}
So the problem is that if std::uncaught_exception() returns true you don't know for sure whether you can safely throw an exception or not. You end up having to avoid throwing an exception when std::uncaught_exception() returns true just to be safe.
There's nothing technically wrong with your code. It's perfectly safe in that you will never accidentally terminate because you threw an exception when it was not safe to. The issue is that it also is not useful, in that it will occasionally also not throw an exception when it is safe to. Your destructor's documentation basically has to say "this might or might not throw an exception."
If it occasionally won't throw an exception, you might as well never throw an exception. That way, you're at least consistent.
Herb Sutter is talking about the situation when an object of class T is destroyed while there is an uncaught exception in an object of class U. std::uncaught_exception() would return true in the T destructor. The destructor would be unable to find out whether it's called during stack unwinding. If it is, it must not throw, otherwise it's business as usual.
The class U would have a problem using class T in the destructor. U would find itself dealing with a useless T object that would refuse to do anything risky in its destructor (that could include writing a log file or committing a transaction to a database).
Herb Sutter suggests never throwing in a destructor, which is a good idea. However, the C++17 offers another option. It introduced std::uncaught_exceptions(), which can be used to find out whether the destructor can throw. Following example shows the problem if complied in C++14 mode. If compiled in C++17 mode, it would work correctly.
#include <exception>
#include <iostream>
#include <string>
class T
{
public:
~T() noexcept(false)
{
#if __cplusplus >= 201703L
// C++17 - correct check
if (std::uncaught_exceptions() == uncaught_exceptions_)
#else
// Older C++ - incorrect check
if (!std::uncaught_exception())
#endif
{
throw (std::string{__PRETTY_FUNCTION__} + " doing real work");
}
else
{
std::cerr << __PRETTY_FUNCTION__ << " cowardly quitting\n";
}
}
private:
#if __cplusplus >= 201703L
const int uncaught_exceptions_ {std::uncaught_exceptions()};
#endif
};
class U
{
public:
~U()
{
try
{
T t;
}
catch (const std::string &e)
{
std::cerr << __PRETTY_FUNCTION__ << " caught: " << e << '\n';
}
}
};
int main()
{
try
{
U u;
throw (std::string{__PRETTY_FUNCTION__} + " threw an exception");
}
catch (const std::string &e)
{
std::cerr << __PRETTY_FUNCTION__ << " caught: " << e << '\n';
}
return 0;
}
Is there a way to determine the exception type even know you caught the exception with a catch all?
Example:
try
{
SomeBigFunction();
}
catch(...)
{
//Determine exception type here
}
Short Answer: No.
Long Answer:
If you derive all your exceptions from a common base type (say std::exception) and catch this explicitly then you can use this to get type information from your exception.
But you should be using the feature of catch to catch as specific type of exception and then working from there.
The only real use for catch(...) is:
Catch: and throw away exception (stop exception escaping destructor).
Catch: Log an unknwon exception happend and re-throw.
Edited:
You can extract type information via dynamic_cast<>() or via typid()
Though as stated above this is not somthing I recomend. Use the case statements.
#include <stdexcept>
#include <iostream>
class X: public std::runtime_error // I use runtime_error a lot
{ // its derived from std::exception
public: // And has an implementation of what()
X(std::string const& msg):
runtime_error(msg)
{}
};
int main()
{
try
{
throw X("Test");
}
catch(std::exception const& e)
{
std::cout << "Message: " << e.what() << "\n";
/*
* Note this is platform/compiler specific
* Your milage may very
*/
std::cout << "Type: " << typeid(e).name() << "\n";
}
}
You can actully determine type inside a catch(...), but it is not very useful:
#include <iostream>
#include <exception>
class E1 : public std::exception {};
class E2 : public std::exception {};
int main() {
try {
throw E2();
}
catch( ... ) {
try {
throw;
}
catch( const E1 & e ) {
std::cout << "E1\n";
}
catch( const E2 & e ) {
std::cout << "E2\n";
}
}
}
There is no standard, portable way to do this. Here's a non-portable way to do it on GCC and clang
#include <iostream>
#include <cxxabi.h>
const char* currentExceptionTypeName()
{
int status;
return abi::__cxa_demangle(abi::__cxa_current_exception_type()->name(), 0, 0, &status);
}
int main()
{
try {
throw std::string();
} catch (...) {
std::cout<<"Type of caught exception is "<<currentExceptionTypeName()<<std::endl;
}
return 0;
}
Output:
Type of caught exception is std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >
provided that c++11 available,
bool throwing_func()
{
// something is wrong...
throw char('5');
// ...
return true;
}
void exception_handler(std::exception_ptr _Eptr)
{
try
{
if (_Eptr) {std::rethrow_exception(_Eptr);}
}
catch(int _Xi)
{
std::cout << "int\n";
}
catch(char _Xc)
{
std::cout << "char\n";
}
catch(const std::exception& _Xe)
{
std::cout << "std::exception " << _Xe.what() << "\n";
}
catch (...)
{// develop more catch cases above to avoid what follows
std::cout << "unhandled exception\n";
// grande problema
}
}
int main()
{
try
{
throwing_func();
}
catch(...)
{
//Determine exception type here
exception_handler(std::current_exception());
}
return 0;
}
If you need to handle exceptions differently based on what they are, you should be catching specific exceptions. If there are groups of exceptions that all need to be handled identically, deriving them from a common base class and catching the base class would be the way to go. Leverage the power and paradigms of the language, don't fight against them!
No.
Doing so would at the very least require you to be able to access the current exception. I do not believe there is a standard way of doing this.
Once you had the exception instance, you would have to use a type inspection algorithm. C++ doesn't have inherent support for this. At best you would have to have a big if/elseif statement with dynamic_cast's to check the type.
This question was asked some time ago and I'm offering this answer as a companion to the accepted answer from 9 years ago. I'd have to concur with that respondent that that answer, "... is not very useful." Further, it opens the door to an exception which was once handled being unhandled. To illustrate, let me build upon the respondent's answer
#include <iostream>
#include <exception>
class E1 : public std::exception {};
class E2 : public std::exception {};
class E3 : public std::exception {};
int main() {
try {
throw E3();
}
catch( ... ) {
try {
// OOOPS!!! E3 is now unhandled!!!!!!
throw;
}
catch( const E1 & e ) {
std::cout << "E1\n";
}
catch( const E2 & e ) {
std::cout << "E2\n";
}
}
}
An alternative to this approach would be the following:
#include <iostream>
#include <exception>
class E1 : public std::exception {};
class E2 : public std::exception {};
class E3 : public std::exception {};
int main() {
try {
throw E3();
}
catch( const E1 & e ) {
std::cout << "E1\n";
}
catch( const E2 & e ) {
std::cout << "E2\n";
}
catch( ... ) {
std::cout << "Catch-all...";
}
}
This second approach seems to be tantamount to the first and has the advantage of specifically handling E1 and E2 and then catching everything else. This is offered only as an alternative.
Please note that, according to C++ draft of 2011-02-28, paragraph 15.3, bullet item 5, "If present, a ... handler shall be the last handler for its try block."
I've tried various ways; this works for me:
Begin by subclassing runtime_error :
/*----------------------------------------------------------------------*/
/* subclass runtime_error for safe exceptions in try/throw/catch */
#include <stdexcept>
/* a little preprocessor magic here -- makes a subclass of runtime_error*/
#define NEWERROR( NE ) class NE : public runtime_error { \
public: NE ( string const& error ) : runtime_error(error) {} }
NEWERROR( FileError );
NEWERROR( NetworkError );
NEWERROR( StringError );
NEWERROR( CofeeError );
/*----------------------------------------------------------------------*/
Then you may create some instances of your exceptions.
/*----------------------------------------------------------------------*/
/* some example pre-defined exceptions */
FileError ReadOnly ( "ReadOnly" );
FileError FileNotFound ( "FileNotFound" );
NetworkError TimeOutExceeded ( "TimeOutExceeded" );
NetworkError HostNotFound ( "HostNotFound" );
CoffeeError OutOfCoffee ( "OutOfCoffee" );
/*----------------------------------------------------------------------*/
Explicitly notify the compiler that your function may throw an exception
or the program will probably terminate at the point thrown, and data could be lost or corrupted
if resources are in use at the time.
"Make sure you can and do catch anything that you can throw."
(I use the generic runtime_error because throwing and catching it covers all of
my exceptions plus the systems' ones as well.)
/*----------------------------------------------------------------------*/
/* example function that may throw an exception */
#include <fstream>
ifstream& getFileStream (string fname) throw (runtime_error)
{
if ( fname == "" )
throw StringError( "<getFileStream> fname:empty string" );
// processing stops here if thrown
try
{
ifstream Inputfstream;
ifstream& ifsref = Inputfstream;
// ifstream has its own <legacy> exception
// mechanisms and procedures
ifsref.exceptions ( ifstream::failbit | ifstream::badbit );
ifsref.open (fname , ifstream::in); // could fail ==> ifstream::failure exception
}
catch (ifstream::failure e)
{
throw FileError( fname + string(e.what() ) );
}
return ifsref;
}
/*----------------------------------------------------------------------*/
then in your try/catch
/*----------------------------------------------------------------------*/
catch (FileNotFound fnf) //catch a specific error
{
if (DEBUG) cerr << "[File Not Found Error: " << fnf.what() << "]" << endl;
... (handle it) ...
}
catch (FileError fe) //catch a specific type
{
if (DEBUG) cerr << "[File Error: " << fe.what() << "]" << endl;
... (handle it) ...
}
catch (runtime_error re ) // catch a generic type
{
if (DEBUG) cerr << "[Runtime error: " << re.what() << "]" << endl;
// determine type by string comparison
if ( re.what() == string("ResourceNotavailable") ) ...
if ( re.what() == string("NetWorkError") ) ...
...
}
catch ( ... ) // catch everything else
{ ... exit, rethrow, or ignore ... }
/*----------------------------------------------------------------------*/
The runtime-error class has good support in the c++ standard libraries,
and compilers know about it internally, and how to optimize memory and dispatch,
so you can use them over different code bases safely and confidently. The code is portable and compatible with many different compilers and architectures.
It may be preferable and somewhat faster to catch each error separately in a catch clause, from more specific to more generic,if you feel a series of string matches is a terrible waste of cpu and memory (the compiler optimizes these though ).
<stdexcept> gives you several kinds of exceptions in 2 groups:
Logic errors:
logic_error
domain_error
invalid_argument
length_error
out_of_range
Runtime errors:
runtime_error
range_error
overflow_error
underflow_error
usage syntax is slightly different for some of them.
Conventional Wisdom in C++ says that your exceptions should be relatively "flat",
meaning that large hierarchies of specific categories of exceptions should be eschewed in
favor of short generic but informative ones for general programming tasks. Domain specific tasks like network system logic, higher maths, etc. may benefit from specificity, but that can be achieved handily by making intelligent error strings with generic runtime/logic exceptions.
Lastly, My Point is: You can achieve all of this by
throwing and catching only runtime_error.
You don't have to create a whole trick-bag of highly specific exceptions
(like java does) for each class, each handling one specific error.
If you're using Visual C++ (managed), you can use the GetType() method to get the type of exception and handle it from there.
E.g.
try
{
// Run the application
Application::Run(mainForm);
}
catch (Exception^ e)
{
String^ exception_type = e->GetType()->ToString();
throw;
}
The string will contain something like "System.ArgumentOutOfRangeException".