It is recommended that you always throw something derived from std::exception and there are a few predefines specialisations such as std::runtime_error
std::exception's interface is given in terms of non-throwing accessors. Great. Now look at the constructor for std::runtime_error
class runtime_error : public exception {
public:
explicit runtime_error (const string &);
};
So if I do this
try {
foo ();
}
catch (...) {
throw std :: runtime_error ("bang");
}
it's entirely possible that foo threw because it's out of memory, in which case constructing the string argument to runtime_error can also throw. This would be a throw-expression which itself also throws: won't this will call std::terminate?
Doesn't this mean we should always do this instead:
namespace {
const std :: string BANG ("bang");
}
...
try {
foo ();
}
catch (...) {
throw std :: runtime_error (BANG);
}
BUT WAIT this won't work either, will it? Because runtime_error is going to copy its argument, which may also throw...
...so doesn't this mean that there is no safe way to use the standard specialisations of std::exception, and that you should always roll your own string class whose constructor only fails without throwing?
Or is there some trick I'm missing?
I think your main problem is that you are doing catch(...) and translating to a std::runtime_error thereby losing all type information from the original exception. You should just rethrow with throw().
Practically, if you are short of memory you are likely have a bad_alloc exception thrown at some point and there's not a lot else you can - or should - do. If you want to throw an exception for a reason other than an allocation failed then you are not likely to have a problem constructing a sensible exception object with meaningful contextual information. If you hit a memory issue while formatting your exception object there's not a lot you can do other than propagate the memory error.
You are right that there is a potential problem if you construct a new string object to construct an exception, but if you want to format a message with context this can't be avoided in general. Note that the standard exception objects all have a const char* constructor (as of last week) so if you have a const char* that you want to use you don't have to construct a new std::string object.
std::runtime_error must copy it's argument, but not necessarily as a new string object. There could be an area of statically allocated memory which it can the contents of its argument to. It only has to fulfil the what() requirements which only requires returning a const char *, it doesn't have to store a std::string object.
This would be a throw-expression which itself also throws: won't this
will call std::terminate?
No, it wouldn't. It would just throw the exception about insufficient memory. The control will not reach the outer throw part.
BUT WAIT this won't work either, will it? Because runtime_error is
going to copy its argument, which may also throw...
Exception classes with a throwing copy-constructors are as evil as throwing destructors. Nothing that can really be done about it.
std::runtime_error is designed to treat the usual runtime errors, not
out of memory or other such critical exceptions. The base class
std::exception does not do anything which may throw; nor does
std::bad_alloc. And obviously, remapping std::bad_alloc into an
exception which requires dynamic allocation to work is a bad idea.
The first thing is what would you want to do if you happen to have a bad_alloc exception because you're out of memory?
I'd say in a classic C++ program, you'd want to have the program somehow trying to tell you what happened and then terminates.
In a classic C++ program you'd then let the bad_alloc exception propagate to the main section of the program. The main will contain an arragement of try/catch like this:
int main()
{
try
{
// your program starts
}
catch( const std::exception & e )
{
std::cerr << "huho something happened" << e.what() << std::endl;
}
catch( ... )
{
std::cerr << "huho..err..what?" << std::endl;
}
}
you'll only use catch( ... ) inside the main and at the starting functions of threads. Contrary to some other languages like Java you're not expected to catch all possible exceptions locally. You just let them propagate until you catch them where you wanted to.
Now if you have code that specifically must check std::bad_alloc, you should only catch( const std::bad_alloc & ) locally. And there it should maybe wise to do something else rather than just rethrow another exception.
I found in The C++ Programming Language ยง14.10 also that the C++ exception-handling mechanism keeps a bit of memory to itself for holding exceptions, so that throwing a standard library exception will not throw an exception by itself. Of course it is possible also to let the exception-handling mechanism run out of memory if you really code something perverted.
So, to sum up, if you do nothing and let big exceptions like bad_alloc propagate nicely where you want to catch them, in my opinion you're safe. And you should not use catch( ... ) or catch(const std::exception & ) anywhere except in the main function and in the starting functions of threads.
Catching all exceptions to rethrow a single exception is really the last thing to do. You lose every advantages you got with the C++ exception-handling mechanism.
Related
I have an API which internally has some exceptions for error reporting. The basic structure is that it has a root exception object which inherits from std::exception, then it will throw some subclass of that.
Since catching an exception thrown in one library or thread and catching it in another can lead to undefined behavior (at least Qt complains about it and disallows it in many contexts). I would like to wrap the library calls in functions which will return a status code, and if an exception occurred, a copy of the exception object.
What is the best way to store an exception (with it's polymorphic behavior) for later use? I believe that the c++0x future API makes use of something like this. So what is the best approach?
The best I can think of is to have a clone() method in each exception class which will return a pointer to an exception of the same type. But that's not very generic and doesn't deal with standard exceptions at all.
Any thoughts?
EDIT: It seems that c++0x will have a mechanism for this. It is described as "library magic". Does that mean that is doesn't require any of the language features of c++0x? if not, are there any implementations which are compatible with c++03?
EDIT: Looks like boost has an implementation of exception copying. I'll keep the question open for any non boost::copy_exception answers.
EDIT: To address j_random_hacker's concerns about the root cause of the exception being an out of memory error. For this particular library and set of exceptions, this is not the case. All exceptions derived from the root exception object represent different types of parsing errors caused by invalid user input. Memory related exceptions will simply cause a std::bad_alloc to be thrown which is addressed separately.
As of C++11, this can be done using std::exception_ptr.
(I use this in a class that makes an std::thread interruptible provided that the underlying thread implementation is a POSIX thread. To handle exceptions that may be thrown in the user's code - which causes problems if they are thrown in a certain critical section of my implementation - I store the exception using std::exception_ptr, then throw it later once the critical section has completed.)
To store the exception, you catch it and store it in the ptr variable.
std::exception_ptr eptr;
try {
... do whatever ...
} catch (...) {
eptr = std::current_exception();
}
You can then pass eptr around wherever you like, even into other threads (according to the docs - I haven't tried that myself). When it is time to use (i.e. throw) it again, you would do the following:
if (eptr) {
std::rethrow_exception(eptr);
}
If you want to examine the exception, you would simply catch it.
try {
if (eptr) {
std::rethrow_exception(eptr);
}
} catch (const std::exception& e) {
... examine e ...
} catch (...) {
... handle any non-standard exceptions ...
}
You have what would be what I think is your best, only answer. You can't keep a reference to the original exception because it's going to leave scope. You simply have to make a copy of it and the only generic way to do that is with a prototype function like clone().
Sorry.
You're allowed to throw anything, including pointers. You could always do something like this:
throw new MyException(args);
And then in the exception handler store the caught pointer, which will be fully polymorphic (below assuming that MyException derives from std::exception):
try {
doSomething(); // Might throw MyException*
} catch (std::exception* pEx) {
// store pEx pointer
}
You just have to be careful about memory leaks when you do it this way, which is why throw-by-value and catch-by-reference is normally used.
More about catch-by-pointer: http://www.parashift.com/c++-faq-lite/exceptions.html#faq-17.8
The reason why catching an exception thrown in one library and catching it in another can lead to undefined behavior is that these libraries could be linked with different Runtime libraries. If you will return exception from a function instead of throwing it you will not avoid that problem.
My utility library has an AnyException class that is basically the same as boost::any without the casting support. Instead, it has a Throw() member that throws the original object stored.
struct AnyException {
template<typename E>
AnyException(const E& e)
: instance(new Exception<E>(e))
{ }
void Throw() const {
instance->Throw();
}
private:
struct ExceptionBase {
virtual void Throw() const =0;
virtual ~ExceptionBase() { }
};
template<typename E>
struct Exception : ExceptionBase {
Exception(const E& e)
: instance(e)
{ }
void Throw() const {
throw std::move(instance);
}
private:
E instance;
};
ExceptionBase* instance;
};
This is a simplification, but that's the basic framework. My actual code disables copying, and has move semantics instead. If needed, you can add a virtual Clone method to the ExceptionBase easily enough... since Exception knows the original type of the object, it can forward the request onto the actual copy constructor, and you immediately have support for all copiable types, not just ones with their own Clone method.
When this was designed, it was not meant for storing caught exceptions... once an exception was thrown, it propagated as normal, so out-of-memory conditions were not considered. However, I imagine you could add an instance of std::bad_alloc to the object, and store it directly in those situations.
struct AnyException {
template<typename E>
AnyException(const E& e) {
try {
instance.excep = new Exception<E>(e);
has_exception = true;
} catch(std::bad_alloc& bad) {
instance.bad_alloc = bad;
bas_exception = false;
}
}
//for the case where we are given a bad_alloc to begin with... no point in even trying
AnyException(const std::bad_alloc& bad) {
instance.bad_alloc = bad;
has_exception = false;
}
void Throw() const {
if(has_exception)
instance.excep->Throw();
throw instance.bad_alloc;
}
private:
union {
ExceptionBase* excep;
std::bad_alloc bad_alloc;
} instance;
bool has_exception;
};
I haven't actually tested that second bit at all... I might be missing something glaringly obvious that will prevent it from working.
Under exceptional circumstances, I want my program to stop processing, output an error to std::cerr, clean up, and exit.
However, calling exit() will not call all the destructors of any objects that have been constructed. I would like to have the destructors called nicely, so I wrapped all the code in a try-catch block, something like this:
int main(int argc, char** argv){
try {
bool something_is_not_right = false;
/* lots of variables declared here */
/* some code that might set something_is_not_right to true goes here */
if(something_is_not_right){
std::cerr << "something is not right!!!" << std::endl;
throw '\0'; // dummy unused variable for throwing.
}
}
catch (...) {}
return 0;
}
In this way, I get guaranteed destruction of all my variables. But I can't seem to find a way to get C++ to throw nothing. throw; has a special meaning in C++; it isn't throwing nothing.
Is there a way to throw nothing?
No
It's not possible to throw nothing. You need to throw something. While you may have seen people use the throw keyword without anything, this just means they are re-throwing the currently handled exception.
This is not a direct answer to your question, but a personal recommendation.
You might want to take a look at the predefined exceptions of stdexcept which cover almost any exceptional behaviour that occurs in a program. In your case I would throw a std::runtime_error. Also, only catch what you expect to be thrown and not catch 'em all. If you really want to catch everything, then catch std::exception (the base class of all standard exceptions).
In my opinion handling unknown exceptions doesn't really make sense and the only logical consequence is to just abort execution.
#include <iostream>
#include <stdexcept>
int main()
{
try
{
bool something_is_not_right = true;
if ( something_is_not_right )
throw std::runtime_error("something is not right!!!");
}
catch (std::runtime_error& e)
{
std::cerr << e.what() << '\n';
throw;
}
}
How do you know that the reason for the catch is your error or something else (out of memory is always a good one). If you detect an error, then you should create and throw the reason for that error in a custom exception. Then in main, you can tell the difference between your detected error and something you didn't expect. It's just good practice.
Well you "can" but it doesn't throw nothing. It terminates.
5.17 Throwing an exception:
Evaluating a throw-expression with an operand throws an exception (15.1)
A throw-expression with no operand rethrows the currently handled exception (15.3).
If no exception is presently being handled, evaluating a throw-expression with no operand calls std::terminate()
This is valid:
int main () {
throw;
return 0;
}
Source used: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4296.pdf
But it won't cleanup anything. std::terminate is used when the cleanups fail.
Otherwise you have to use operand, and then this section becomes relevant:
15.1 Throwing an exception [except.throw]
Throwing an exception copy-initializes (8.5, 12.8) a temporary object, called the exception object. The temporary is an lvalue and is used to initialize the variable declared in the matching handler (15.3).
So you have to pass something that is able to be initialized, which by definition cannot be nothing.
In order to ensure full cleanup you have to throw an exception and catch it somewhere. Implementations are not required to clean up stack objects when an exception is thrown but not caught. The requirement (in [except.handle]/9) when an exception is thrown but not caught is that the program calls std::terminate(), and it's implementation-defined whether stack objects are cleaned up.
As mentioned in many previous answers, one should throw exceptions by value and catch them by reference ([A], [B]), such as
try {
// throw std::exception();
}
catch(std::exception &e) {
// handle exception
}
If you aren't going to make use of the exception itself (even though you should), this will however generate annoying "unused variable" warnings on compile. To avoid these, you can omit the parameter (e in the example above), at which point the catch block will trigger for the defined exception, but you won't have a variable to bother with.
However, almost every time I see this variable-less catch block, it is not declared by reference, but by value, as in
try {
// throw std::exception();
}
catch(std::exception) {
// handle exception
}
Even Our Lord and Savior has posted an answer this way (as have others). I did find one instance where references are used, though.
Since the variable isn't used, slicing isn't a problem, so there should be no effective difference between catching by value or by reference. However, why do people seemingly make a distinction between the with-variable and without-variable cases? Saving themselves the effort of adding that ampersand?
And, micro-optimizing as it may be (especially given how exceptional exceptions should be), doesn't the by-value case incur a casting cost (to see if the catch is appropriate for the thrown exception) mitigated when done by-reference?
Since the variable isn't used, slicing isn't a problem.
But you'd be forcing a copy in the case of a slice. Not that this is particularly problematic, since the exception ought to be on the rarely-taken code path.
However, if you were to re-throw the exception as a nested exception after a copy/slice then the final result might be surprising. e.g.:
struct E : std::runtime_error { using std::runtime_error::runtime_error; };
throw E("");
...
catch(std::runtime_error)
{
std::throw_with_nested(std::logic_error(""));
}
... further down the call stack...
catch(std::exception& e)
{
// what did we actually catch? std::runtime error nested in a std::logic_error, or
// E nested in a std::logic_error?
}
Is it safe to use unique_ptr?
When I use cout in destructor, sometimes it called more then one time. - so it make copy time-to-time. if it take two copy from one object - data can be lost..
#include <memory>
class MyException
{
std::unique_ptr<Type> data;
MyException();
~MyException() {cout<<"test"<<endl;}
MyException(MyException ex&);
};
int main()
{
try
{
try
{
throw MyException();
}
catch (const MyException& ex)
{
throw;
//or?
throw ex; //will be copied?
}
return 0;
}
catch(const MyException/*& will be missed. will ex be copied?*/ ex)
{
throw; //wich ex will be re-throw, copy or original?
//or?
throw ex; //will be copied?
}
}
Can I be sure, that data will not be lost between re-throws?
And is this good practic to use ptr inside exception to collect error info from different levels?
Also, can MyException.data be lost after:
std::exception_ptr ex = std::current_exception();
std::rethrow_exception(ex);
As you discovered, you should always say throw; when you want to re-throw an exception, not not throw ex;. Indeed, throw ex; will copy (and slice, if ex is a reference to a base class!).
So, always catch by reference, and always re-throw without naming the exception.
With gcc 4.7.3 your example doesn't compile, complaining about a missing copy constructor for MyException. This is in the line where it's first thrown, so throw MyException() itself already wants to make a copy (at least in gcc). See also this stackoverflow question and the C++ FAQ.
To answer your question about whether using pointers in exceptions is good practice, I would generally say no. Unless the data to be piggybacked onto the exception is huge (which would likely be a design problem), a stack allocated data structure should be preferred. Performance shouldn't be the main concern during exception handling anyway, so copying stuff around isn't a real problem.
If you really need a pointer (maybe Type has no copy constructor and you can't change that), using shared_ptr could help you in a pinch, although I feel like that would be an ugly hack. I would probably try and reduce the information passed via the exception to the bare minimum that would help callers identify and handle the problem.
Edit: I found the relevant section in the C++ standard, section 15.1, paragraph 5:
When the thrown object is a class object, the copy/move constructor and the destructor shall be accessible, even if the copy/move operation is elided.
So it's actually not legal C++ to throw an exception object without a copy constructor.
Is it proper to use throw new FoobarException(Baz argument); or throw FoobarException(Baz argument);?
When catching I always use catch(FoobarException& e) "just in case" but I never could find a solid answer whether I had to use new or not in C++ (Java definitely) or if it was just a preference of the programmer.
Exceptions in C++ should be thrown by value, and caught by reference.
So this is the proper way:
try
{
throw FoobarException(argument);
}
catch( const FoobarException &ex )
{
cout << ex.what() << endl;
}
Don't throw an exception created with new, since who's responsible for deleting it is not well-defined. In addition, performing allocations during error handling can throw another exception, obscuring the original problem.
You don't have to catch by const reference (non-const will work fine), but I like doing it anyway. You should however always by reference (not by value) to catch the exception polymorphically. If you don't, the exception's type could be sliced.
unless there is some special requirement not to, I always throw by value and catch by const reference. This is because the new itself could throw an exception as well, during error handling, it is best to avoid things which can cause exceptions.