try-catch without argument, use reference? - c++

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?
}

Related

C++ colon syntax with function body

I've encountered an example (for a trivial function-try-block), from which seems to utilize one of the more obscure of aspects of C++ syntax to which (like most obscure aspects of the language) I can not seem to find documentation for.
I've searched the Google to no avail, with all searches returning (rather uselessly) only for constructor initialization (which I'm familiar with), but what I would like to know is the importance of the body: and handler: statements in this constructor block:
class foo{
foo() try
//initalizer list that could throw
{
body:
//do stuff that could possibly throw
} catch(std::exception &e) {
handler:
throw;
}
};
The original author abruptly adds this syntax in a single example and I would like to know the implications of such linguistic constructs
The XXX: is a label. It doesn't serve any functional purpose in the code you posted. It may have been put in by the author to help them organize the code.
You can use labels with goto statements, as in goto XXX; to jump to that point in your code, although I'll leave it up to you to decide if that is a good think or now.
foo::foo()
try
{
body:
//... do stuff that could possibly throw
}
catch(std::exception &e){
handler:
throw;
}
That piece of code has two rather unusual constructs. The first is what you already pointed out and has already been explained in mjk's answer: body and handler are labels. Labels are used for gotos, and that in turn can be used for flow control (determining where the code should continue executing). Now, gotos should rarely be used, as there are very few cases where they cannot be substituted by other flow controls (if,for,while,do...) that would make it more readable. Since gotos are rarely used, labels are also rarely used.
The second interesting construct is the function-level try block:
foo::foo()
try {
} catch (std::exception const &) {
}
Note that there try catch is not inside the constructor body, but actually outside the {}. This is also a rare construct. It was designed to support catching an exception during the evaluation of the initializer list in the constructor (which in the code above is implicit). If the type has a base, or members whose constructors could throw, the constructor's body would never be evaluated and a regular try-catch would not be useful to treat that exception. The function level try block encloses also the initializer list and will catch any exception thrown during the evaluation of the different submember's constructors. It is a rarely used construct since you cannot really do much in the catch block. The exact state of what has been or has not been constructed is unknown and cannot be verified so the only possible use is to rethrow either the same exception or a different one. The syntax in a more complete example would be:
T::T()
try
: base1(args), base2(), member1(), member2() //...
{
// body
} catch (exception1 const& ex1) {
// ...
throw; // rethrow same exception
} catch (exception2 const& ex2) {
// ...
throw different_exception();
}

Not All Control Paths Return a Value? Warning

Ive got a short bit of code that is giving me the following the warning upon compilation:
'BGOLUB::Containers::Stack::Pop' : not all control paths return a value
Here is the code:
template<typename T>
T Stack<T>::Pop()
{
try
{
if (m_index<0) throw OutOfBoundsException(m_index);
--m_index;
return(m_array[m_index]);
}
catch(OutOfBoundsException&)
{
cerr<<"Underflow Index = "<<m_index<<endl;
}
catch(...)
{
cerr<<"Unhandled Error Occured"<<endl;
}
}
Any advice?
Many thanks!
Any advice?
The compiler is giving you the best advice. Not all the control paths in your function contain a return statement, and your function is supposed to return a value.
If an exception is thrown and control is transferred to a catch handler, that handler will print something to cerr and then flow off the end of your function without actually returning anything.
This is Undefined Behavior. Per Paragraph 6.6.3/2 of the C++11 Standard:
[..] Flowing off the end of a function is equivalent to a return with no value; this results in undefined
behavior in a value-returning function.
For default-constructible values, you could fix this by adding a return T() statement right before the end of your function:
template<typename T>
T Stack<T>::Pop()
{
try
{
// ...
}
catch (OutOfBoundsException&)
{
// ...
}
catch (...)
{
// ...
}
return T();
// ^^^^^^^^^^^
}
A more reasonable approach is, however, to not have Pop() swallow the exception, but rather re-throw it. Pop() does not have strategic-level information on how to recover from an error occurred in this context:
template<typename T>
T Stack<T>::Pop()
{
try
{
// ...
}
catch (OutOfBoundsException&)
{
// ...
throw; // <== Re-throw after printing the diagnostic
}
catch (...)
{
// ...
throw; // <== Re-throw after printing the diagnostic
}
}
Even better would be if the responsibility for logging an error message did not belong to Pop() at all, since Pop() is likely supposed to be re-used by code with different requirements in this sense (some may not want to log anything, some may want to log messages to a file, some may want to log messages in a different language, and so on).
So a more reasonable version of your function would actually be:
template<typename T>
T Stack<T>::Pop()
{
if (m_index<0) throw OutOfBoundsException(m_index);
--m_index;
return(m_array[m_index]);
}
In general, you should try (no pun intended) to avoid try/catch blocks unless you have to:
Translate an exception
Recover from the error (but you need strategic knowledge for doing this)
If this not your task (as is the case for a function like Pop() above), in most situations the best thing to do is to not handle exceptions at all and let them propagate up the call stack.
To quote Dave Abrahams:
Often the best way to deal with exceptions is to not handle them at all. If you can let them pass through your code and allow destructors to handle cleanup, your code will be cleaner.
To avoid leaking memory, resources, or in general responsibilities, write code that is exception-safe by using adequate RAII wrappers. Excellent guidelines in this sense are given in this two-part talk by Jon Kalb.
In particular, avoid writing catch (...) handlers: exceptions were invented to prevent programmers from ignoring errors, and swallowing them all in a universal handler without re-throwing them is the best way to ignore them.
NOTE:
Notice, that your implementation of Pop() is a bit problematic: what happens if the copy constructor or move constructor of T throws when returning the element back to the caller, after you already modified the stack pointer?
This is the reason why the C++ Standard Library defines two separate functions pop() and top(): because it allows to offer strong guarantee, i.e. to give transactional semantics to your pop() operation - either the element is removed without exceptions being thrown, or the function had no effect at all.
You need either rethrow exceptions, or return something probably T() at the end of function.
When the exception is thrown, it will be caught by one of the two catch statements. However, they still need to return a value from the function. You could place a return statement right at the end of your function.
However, if Pop throws an exception because the Stack is empty, it makes much more sense for it to let the exception propagate out of the function. Why is Pop itself attempting to handle the exceptional situation?
I would recommend using brackets with all of your if statements, even with one-line bodies. They are not strictly necessary, and you can write perfectly legal code without them, but they make your code much more readable, and errors such as this will be much easier to find.
Additionally, it seems you have a fundamental misunderstanding of how exceptions work. If your code were to encounter an exception, it would jump straight to the catch block, and not execute any subsequent code in the try block. Therefore, the return statement in you try block will never be reached, and your function will not return anything, since the catch blocks lack return statements.
You can resolve this issue by adding a return statement in your catch block.

std exceptions inviting unsafe usage?

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.

C++: Throwing exceptions, use 'new' or not?

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.

What is the point of `void func() throw(type)`?

I know this is a valid c++ program.
What is the point of the throw in the function declarement? AFAIK it does nothing and isnt used for anything.
#include <exception>
void func() throw(std::exception) { }
int main() { return 0; }
It specifies that any std::exception can be thrown from func(), and nothing else. If something else is thrown, it will call an unexpected() function which by default calls terminate().
What this means is that throwing something else will almost certainly terminate the program, in the same manner as an uncaught exception, but the implementation will have to enforce this. This is normally much the same as putting a try{...}catch(){...} block around func(), which can inhibit performance.
Usually, exception specifications aren't worth it, according to the Guru of the Week column about it. The Boost guidelines say that there might be a slight benefit with a blank throws() for a non-inline function, and there are disadvantages.
That is an exception specification, and it is almost certainly a bad idea.
It states that func may throw a std::exception, and any other exception that func emits will result in a call to unexpected().
This is a C++ exception specification. It declares that the particular function will potentially throw a std::exception type.
In general though exception specifications in C++ are considered a feature to avoid. It's an odd feature in that it's behavior is declared at compile time but only checked at runtime (very different from say Java's version).
Here is a good article which breaks down the feature
http://www.gotw.ca/publications/mill22.htm
This is an exception specification. It says that the only exception that func() can throw is std::exception (or a derivative thereof). Attempting to throw any other exception will give std::unexpected instead.
Exception specification. The type(s) following the throw keyword specifies exactly what all, if any, exceptions the function can throw. See 15.4 of the draft.
Note: A function with no exception-specification allows all exceptions. A function with an empty exception-specification, throw(), does not allow any exceptions.
Basically this:
void func() throw(std::exception,B) { /* Do Stuff */}
Is just shorthand fro this:
void func()
{
try
{
/* Do Stuff */
}
catch(std::exception const& e)
{
throw;
}
catch(B const& e)
{
throw;
}
catch(...)
{
unexpected(); // This calls terminate
// i.e. It never returns.
}
}
Calling terminate() is rarely what you want, as the stack is not unwound and thus all your efforts in RAII is wasted. The only exception to the rule is declaring an empty throw list and this is mainly for documentation purposes to show that you are supporting the no-throw exception gurantee (you should still manually catch all exceptions in this situation).
Some important (imho) places that should be no-throw are destructors and swap() methods. Destructors are rarely explicitly marked no-throw but swap() are quite often marked no-throw.
void myNoThrowFunc() throws() // No-Throw (Mainlly for doc purposes).
{
try
{
/* Do Stuff */
}
catch(...) // Make sure it does not throw.
{
/* Log and/or do cleanup */
}
}