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.
Related
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?
}
This question already has answers here:
catch exception by pointer in C++
(5 answers)
Closed 9 years ago.
I read the "Programming: Principles and Practice using C++" book (Bjarne Stroustrup). Sometimes the author writes:
catch (runtime_error e)
but sometimes he writes:
catch (runtime_error& e)
As I know, the first variant creates the copy of source, but the second uses the link. Or am I mistaken? Is this not important for the "catch" in this case?
I would have expected that most of the time, he would use:
catch ( runtime_error const& e )
The difference between catch by value and catch by reference is
exactly the same as pass by value and pass by reference for
a function parameter. The most important difference is that
when catching by reference, the dynamic type can be
a derived type, by value will result in slicing (because of the
copy).
Also, if you catch by non-const reference, and modify the
exception object, then rethrow, it is the modified object which
will propagate.
In order to avoid unnecessary copies AND slicing, you should always catch the exception by reference. Especially in the cases, when you plan to re-throw; it.
Catch by value
catch (runtime_error e)
versus catch by reference
catch (runtime_error& e)
You'd use the later when you have (usualy polymorphic) exception class hierarchy and you want to catch exceptions of all the derived types in a single catch clause.
For example, all the exception classes from the standard library derive from std::exception, so you can do something like this:
try {
int i;
std::cin >> i;
switch (i) {
case 1: throw std::range_error();
case 2: throw std::overflow_error();
case 3: throw std::undefflow_error();
default: throw std::logic_error();
}
} catch (std::exception& e) {
// handle all the exceptions the same way,
// but print a diagnostic message polimorphicaly
std::cout << "I caught: " << e.what() << '\n';
}
If, instead by reference, you'd catch by value, you'd always catch a std::exception, sliced off of the derived part of the object.
You should always catch by reference; there is absolutely no reason to catch by value.
Don't trust everything that is written. ;-)
We have an custom error class that is used whenever we throw an exception:
class AFX_CLASS_EXPORT CCLAError : public CObject
It has the following copy constructor defined:
CCLAError(const CCLAError& src) { AssignCopy(&src); } // (AssignCopy is a custom function)
It was originally written and compiled / linked with MSVC6 (Visual Studio 2003). I am in the process of doing necessary changes to get it to compile and link against MSVC8+ (VS 2008+)
When the msvc8 linker is invoked, i get the following error:
LNK2001: unresolved external symbol "private: __thiscall CObject::CObject(class CObject const &)" (??0CObject##AAE#ABV0##Z)
I understand what the error is telling me: no copy constructor is defined for some child of CObject, so its going all the way up the inheritance tree until it hits CObject, which as no copy constructor defined.
I first saw the error when compiling the library that defines and first throws a CCLAError, which is why I am proceeding as if that is the cause.
I was able to resolve the error by changing
throw CCLAError( ... )
to
throw new CCLAError( ... )
and
catch(CCLAError& e)
{
throw e;
}
to
catch(CCLAError& e)
{
throw;
}
However, I do not understand why re-throwing a caught exception would invoke the copy constructor. Am I missing somethnig completely obvious? Subsequently, why would removing the variable holding a reference to a caught exception cause the copy constructor to not be invoked?
The type of the object thrown must be copyable because the throw expression may make a copy of its argument (the copy may be elided or in C++11 a move may take place instead, but the copy constructor must still be accessible and callable).
Rethrowing the exception using throw; will not create any copies. Throwing the caught exception object using throw e; will cause a copy of e to be made. This is not the same as rethrowing the exception.
Your "updated" code does not work as you expect. catch (CCLAError&) will not catch an exception of type CCLAError*, which is the type of the exception thrown by throw new CCLAError(...);. You would need to catch CCLAError*. Do not do this, though. Throw exceptions by value and catch by reference. All exception types should be copyable.
However, I do not understand why re-throwing a caught exception would invoke the copy constructor.
It doesn't, but re-throwing the thrown exception is done with throw;. When you do throw e; you are requesting to throw a copy of the caught exception.
Several points:
1st of all don't call throw new foo() use throw foo
2nd when your write:
catch(foo const &e) {
throw e;
}
You actually create a new exception, and if for example the exception that
was thrown is subclass of foo they my calling throw e you would loose this
information and actually use a copy constructor to generate foo from e - whatever
it was.
Now when you call
catch(foo const &e) {
throw;
}
You don't create a new exception but rather propagate the same exception.
So: never use throw e; to propagate the exception forward, use throw;
When you throw an exception, the object you're throwing generally resides on the stack. The stack is getting cleaned up as part of the process of throwing, so the compiler must make a copy that can continue to live beyond that point.
When you throw an object with new, you're not throwing the actual object but you're throwing a pointer to the object. That means your catch block must also catch a pointer rather than a reference. Don't forget to delete the pointer or you'll have a memory leak!
When the catch block uses throw; instead of throw e; it can reuse the copy it made earlier and there's no need to make another copy.
It appears that you have misunderstood what re-throw means. When you do -
catch(CCLAError& e)
{
throw e;
}
-- you are NOT rethrowing. Instead, as you have observed, you are indeed creating a copy of the new exception. Instead (again, as you have found for yourself), this is what is technically the correct way to re-throw:
catch(CCLAError& e)
{
throw;
}
Read chapter 14 in Stroustrup's TC++PL (14.3.1 deals with rethrowing).
Also, you do NOT have to do -
throw new CCLAError( ... )
Instead, do -
throw CCLAError( ... )
-- like you were doing before, only receive by CONST reference (you cannot hold a reference to a temporary).
catch(const CCLAError &e)
The language specification allows the compilers to make as many copies of the original object as they want. There is no restriction on the number of copies.
That means, your custom exception class must have an accessible copy-constructor, either the compiler generated one, or user-defined one.
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.
// http://www.parashift.com/c++-faq-lite/misc-technical-issues.html
class BadConversion : public std::runtime_error {
public:
BadConversion(std::string const& s)
: std::runtime_error(s)
{ }
};
inline std::string stringify(double x)
{
std::ostringstream o;
if (!(o << x))
throw BadConversion("stringify(double)");
// throw new BadConversion("stringify(double)");
return o.str();
}
[Q1] When we throw an exception in the function, what is the difference between throw new ClassName() and throw ClassName()?
[Q2] Which one is better?
Thank you
[A1] With throw new, you'll have to catch a pointer. The language doesn't specify in this case who is responsible for deallocation, so you'll have to establish your own convention (typically you'd make the catcher responsible). Without new, you'll want to catch by reference.
[A2] If you're in a framework that commonly throws pointers, you may want to follow suit. Else, throw without new. See also the C++ FAQ, item 17.14.
throw new ClassName() throws pointer to ClassName. You need to catch (ClassName * pc). It's not good idea. If new returns null or throws then you have null pointer when you catch or you have double exception.
throw ClassName() is usual way to throw an exception. You need to catch (const ClassName & pc).
throw new BadConversion(”xxx“) is creating a new object on the heap and throwing a pointer to it. That object will have to be deleted by the catch block. I can't think of a good reason why you would want to do that.
The other version is taken care of by RAII, use that.
Within your code base you should choose one method and stick to it for consistency.
If some of your code throws pointers and other libraries throws objects then your catch clauses may get a bit convoluted as you may need catches for both pointers and objects of the same type.
I personally prefer to throw objects rather than pointers (the main reason I choose this rather than pointers is that it mimics the standard library). Though it is quite feasible to throw pointers the question of ownership rears its ugly head. Who (if anybody) is responsible for deleting the pointer?