I like boost::exception quite a bit, but I'm quite bothered it does not provide a proper what() function out of the box. Now don't get confused, it does have a nice boost::diagnostic_information that contains all the information I would like to see in my hypothetic what() function but since boost::exception does not inherit from std::exception the what() function I get if I multiple inherit (as suggested from the tutorial, see line below) is the default useless what() from the std::exception base that explains nothing about the exception.
struct my_exception: virtual std::exception, virtual boost::exception { };
Now obviously I tried to override what() and make it return boost::diagnostic_information but somehow it just does not work, so I'm a bit puzzled. That might be because it would loop but I'm not quite sure.
PS: The reason I want to implement what() right is that it is shown by default by a lot of tools if your program dies from them (e.g. the gnu compiler will show a nice fatal error, and display what(), boost unit tests tools etc.).
Here's a link to the test code below
#include <boost/exception/all.hpp>
struct my_exception: virtual std::exception, virtual boost::exception {};
struct my_exception2: virtual std::exception, virtual boost::exception {
virtual const char* what() const throw() {
return "WHAT";
}
};
struct my_exception3: virtual std::exception, virtual boost::exception {
virtual const char* what() const throw() {
return boost::diagnostic_information(this).c_str();
}
};
int main() {
try {
BOOST_THROW_EXCEPTION(my_exception());
} catch (const std::exception& e){
std::cout << e.what() << std::endl;
//This is useless ___ std::exception
}
try {
BOOST_THROW_EXCEPTION(my_exception());
} catch (const boost::exception& e){
std::cout << boost::diagnostic_information(e) << std::endl;
//This is what I'd like to see ___ main.cpp(39): Throw in function int main() ___ Dynamic exception type: boost::exception_detail::clone_impl ___ std::exception::what: std::exception
}
try {
BOOST_THROW_EXCEPTION(my_exception2());
} catch (const std::exception& e){
std::cout << e.what() << std::endl;
//Overriding what usually works ___ WHAT
}
try {
BOOST_THROW_EXCEPTION(my_exception3());
} catch (const std::exception& e){
std::cout << e.what() << std::endl;
//But somehow here it does not work ___ Unknown exception.
}
}
First, boost::diagnostic_information takes an exception by (const) reference, and this is a pointer:
return boost::diagnostic_information(*this).c_str();
^-- here
Second, once you've fixed that, as you've correctly anticipated this results in infinite recursion as boost::diagnostic_information calls std::exception::what(). It is possible to work around this with a guard member or something similar:
struct my_exception3: std::exception, boost::exception {
mutable bool in_what = false;
virtual const char* what() const throw() {
struct g { bool &b; ~g() { b = false; } } guard{in_what};
return in_what ? "WHAT" : (in_what = true, boost::diagnostic_information(*this).c_str());
}
};
Finally, you're using c_str from a destructed temporary string. I'll leave the solution to that problem as an exercise.
And the winner is...
namespace boost {
char const * diagnostic_information_what( boost::exception const & e ) throw();
}
Related
I am taking a course online and came across some syntax I am not really sure I understand.
#include <iostream>
#include <exception>
using namespace std;
class derivedexception: public exception {
virtual const char* what() const throw() {
return "My derived exception";
}
} myderivedexception;
int main() {
try {
throw myderivedexception;
}
catch (exception& e) {
cout << e.what() << '\n';
}
}
My Problem is with:
virtual const char* what() const throw()
What does this line mean?
also, what is with the
} myderivedexception;
in the end of the class declaration?
This line:
virtual const char* what() const throw()
says that what is a virtual method that returns a pointer to a constant char (which means it can be used to return a string literal, or the contents of a std::string obtained by calling the string::c_str() function), is itself constant so it doesn't modify any class members, and it does not throw any exceptions.
This line:
} myderivedexception;
creates an instance of the derivedexception class named myderivedexception. You probably do not want to do this, but instead throw an unnamed exception:
throw derivedexception();
I've problem with exceptions:
#include <iostream>
#include <cstring>
#include <exception>
class except :public std::exception
{
char* err;
public:
except(const char* s) noexcept
{
err = new char[strlen(s) + 1];
strcpy(err, s);
err[strlen(s)] = 0; //is it necessary??
}
virtual const char* what() noexcept
{return err;}
virtual ~except() noexcept
{delete err;}
};
double div(const double& a, const double& b) noexcept
{
if (b == 0.0)
throw except("DIVIDED BY 0");
return a / b;
}
int main()
{
try
{
std::cout << div(5.0, 0.0);
}
catch (std::exception &ex)
{
std::cout << ex.what();
}
return 0;
}
I want to print "DIVIDED BY 0" but I get:
terminate called after throwing an instance of 'except'
what(): std::exception
Aborted
Process returned 134 (0x86)
Shall I put noexcept in every function/member function that doesn't throw any exceptions?
Is err[strlen(s)] = 0 necessary? (in except::except(const char* s))
I want to print "DIVIDED BY 0" but I get: terminate called after throwing an instance of 'except'
double div(const double& a, const double& b) noexcept
You are claiming that you won’t throw an exception, but you are lying. The result is the call to std::terminate when you actually throw.
The problem is a actually twofold. Firstly, as #manni66 suggests, div should not be declared noexcept and this does cause a run-time error, but removing it does not solve the issue.
The second problem is that what has been declared:
virtual const char* what() noexcept;
whereas it's declared in std::exception as:
virtual const char* what() const noexcept;
and this difference in signature means that when it's caught by the handler for std::exception, it calls std::exception::what() and not except::what()
A couple of points worth mentioning:
Ensure that your function overloads exactly match those in the base class.
If you are expecting a certain type of exception to be thrown then try to catch that first with a specific handler and use an appropriate name for the exception for clarity.
As others have mentioned, please try to use the std::string class if you can. It will make things easier and safer. Although in this case, as point two eludes to, a string member is not really necessary as the class is specific enough not to need further qualification.
Don't create an exception class unless it's adding some specific value (though the value, may simply be that you want to specifically catch a certain type of exception and handle in a certain way.) If you wanted a more general exception then std::runtime_error or in this case std::overflow_error would be decent choices and both take a std::string as an argument to the constructor, so no need to create your own exception class.
For example:
#include <exception>
using namespace std;
class divide_by_zero : public std::exception
{
public:
virtual const char* what() const noexcept { return "DIVIDED BY 0"; }
};
double div(const double& a, const double& b)
{
if (b == 0.0)
throw divide_by_zero();
return a / b;
}
int main()
{
try
{
std::cout << div(5.0, 0.0);
}
catch (divide_by_zero &ex)
{
std::cout << ex.what();
}
catch (std::exception &ex)
{
std::cout << ex.what();
}
return 0;
}
Output:
DIVIDED BY 0
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.
I want to call a function that may throw an exception. If it does throw an exception, I want to catch it and pass the exception object to a handler function. The default implementation of the handler function is simply to throw the exception. Here is whittled-down code to illustrate the issue:
struct base_exception : exception {
char const* what() const throw() { return "base_exception"; }
};
struct derived_exception : base_exception {
char const* what() const throw() { return "derived_exception"; }
};
void exception_handler( base_exception const &e ) {
throw e; // always throws a base_exception object even if e is a derived_exception
}
int main() {
try {
throw derived_exception();
}
catch ( base_exception const &e ) {
try {
cout << e.what() << endl; // prints "derived_exception" as expected
exception_handler( e );
}
catch ( base_exception const &e ) {
cout << e.what() << endl; // prints "base_exception" due to object slicing
}
}
}
However, the throw e in exception_handler() throws a copy of the static type of the exception, i.e., base_exception. How can I make exception_handler() throw the actual exception having the correct run-time type of derived_exception? Or how can I redesign things to get what I want?
You can put a throw_me virtual function in the base exception class, and have every derived class override it. The derived classes can throw the proper most derived type, without slicing. Even though the function has the same definition in each class, they're not the same - the type of *this is different in each case.
struct base_exception : exception
{
char const* what() const throw() { return "base_exception"; }
virtual void throw_me() const { throw *this; }
};
struct derived_exception : base_exception
{
char const* what() const throw() { return "derived_exception"; }
virtual void throw_me() const { throw *this; }
};
void exception_handler( base_exception const &e ) {
e.throw_me();
}
You can use throw; to re-throw the exception that was caught. You could also use a template.
template<typename T> void rethrow(const T& t) { throw t; }
Throw by value, catch by reference. It'll save you a lot of headaches.
What you are looking for is called "propagating" the exception. To do so, you have to use the throw keyword without parameters inside the catch block. It will not copy the exception and the exception will be caught by the next catch block on its way or will make your program abort if it's not caught again.
Basically I want to simulate .NET Exception.InnerException in C++. I want to catch exception from bottom layer and wrap it with another exception and throw again to upper layer. The problem here is I don't know how to wrap the catched exception inside another exception.
struct base_exception : public std::exception
{
std::exception& InnerException;
base_exception() : InnerException(???) { } // <---- what to initialize with
base_exception(std::exception& innerException) : InnerException(innerException) { }
};
struct func1_exception : public base_exception
{
const char* what() const throw()
{
return "func1 exception";
}
};
struct func2_exception : public base_exception
{
const char* what() const throw()
{
return "func2 exception";
}
};
void func2()
{
throw func2_exception();
}
void func1()
{
try
{
func2();
}
catch(std::exception& e)
{
throw func2_exception(e); // <--- is this correct? will the temporary object will be alive?
}
}
int main(void)
{
try
{
func1();
}
catch(base_exception& e)
{
std::cout << "Got exception" << std::endl;
std::cout << e.what();
std::cout << "InnerException" << std::endl;
std::cout << e.InnerException.what(); // <---- how to make sure it has inner exception ?
}
}
In the above code listing I am not sure how to initialize the "InnerException" member when there is no inner exception. Also I am not sure whether the temporary object that is thrown from func1 will survive even after func2 throw?
Since C++ 11 you have new options:
You can use std::exception_ptr.
The exception is then preserve until last exception_ptr to this
exception is destroyed.
struct base_exception : public std::exception
{
std::exception_ptr InnerException;
base_exception() {}
base_exception(std::exception& innerException)
: InnerException(std::make_exception_ptr(innerException))
{}
};
Or you can simply use std::nested_exception.
You should also take a look at boost exception for an alternative solution to wrapping.
Also I am not sure whether the
temporary object that is thrown from
func1 will survive even after func2
throw?
No. Unless you rethrow the exception with throw;. You could implement this if you'd allow only some (limited) set of exception types.
//inversion of the problem :)
struct base_exception : public std::exception
{
std::list<base_exception*> snowball;
base_exception() { }
void add(base_exception* e) { snowball.push_back(e); }
};
void func2()
{
func2_exception e;
e.add(new func2_exception());
throw e;
}
void func1()
{
try
{
func2();
}
catch(base_exception& e)
{
e.add(new func1_exception());
throw e;
}
}
int main(void)
{
try
{
func1();
}
catch(base_exception& e)
{
std::cout << "Got exception" << std::endl;
//print info in the direct order of exceptions occurence
foreach(base_exception* exception, e.snowball)
{
std::cout << exception->what();
std::cout << "next exception was:" << std::endl;
}
}
}
hmmmm...
One problem with the inner exception is the possibility to throw it again while maintaining polymorphic behaviour.
This can be (somewhat) alleviate by actually managing the exception lifetime yourself and providing polymorphic copies.
// Base class
class exception: virtual public std::exception, private boost::noncopyable
{
public:
virtual exception* clone() const = 0;
virtual void rethrow() const = 0; // throw most Derived copy
};
// ExceptionPointer
class ExceptionPointer: virtual public std::exception
{
public:
typedef std::unique_ptr<exception> pointer;
ExceptionPointer(): mPointer() {}
ExceptionPointer(exception* p): mPointer(p) {}
ExceptionPointer(pointer p): mPointer(p) {}
exception* get() const { return mPointer.get(); }
void throwInner() const { if (mPointer.get()) mPointer->rethrow(); }
virtual char* what() const { return mPointer.get() ? mPointer->what() : 0; }
private:
pointer mPointer;
};
How to use ?
try
{
// some code
}
catch(exception& e)
{
throw ExceptionPointer(e.clone());
}
// later on
try
{
}
catch(ExceptionPointer& e)
{
e.throwInner();
}
As stated by others, boost::exception is a nice option. However, like all options that use a common base class approach, they rely on all thrown exceptions being derived from that base class. If your intermediary catch handlers need to add information to an exception from a third party library it won't work.
An option that might be sufficient is to have intermediary catch handlers like this:
catch (std::exception& ex)
{
std::string msg = ex.what();
msg.append(" - my extra info");
ex = std::exception(msg.c_str()); // slicing assignment
throw; // re-throws 'ex', preserving it's original type
}
This only works for implementations of std::exception that provide a constructor taking a string parameter (e.g. VC++). The std::exception constructor taking a string is a non-standard extension.