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.
Related
I am not sure if this is a issue with the compiler or if I am doing something wrong. I am using Visual Studio 2013 compiler.
I have a class where I need to acquire significant amount of resources in my constructor initializer list most of which can throw an exception. I wrapped up the member initializer list in a function try block and caught the exception there. But my program still aborts even though the catch clause doesn't re-throw the exception. I am not allowed to post the actual code. So I have reproduced the issue with this equivalent demo code. Can someone please help me address this?
#include <iostream>
using namespace std;
class A{
public:
A() try : i{ 0 }{ throw 5; }
catch (...){ cout << "Exception" << endl; }
private:
int i;
};
int main(){
A obj;
}
On executing this code I get a windows alert "abort() has been called". So I guess the system is treating this as an uncaught exception and calling terminate().
On the other hand if I wrap the construction of the object in main() in a try-catch block then the exception is caught properly and the program terminates normally.
Can someone please tell me if I am doing something wrong here?
There's a relevant gotw
http://gotw.ca/gotw/066.htm
Basically even if you don't throw in your catch block, the exception will automatically be rethrown
If the handler body contained the statement "throw;" then the catch
block would obviously rethrow whatever exception A::A() or B::B() had
emitted. What's less obvious, but clearly stated in the standard, is
that if the catch block does not throw (either rethrow the original
exception, or throw something new), and control reaches the end of the
catch block of a constructor or destructor, then the original
exception is automatically rethrown.
This is normal behaviour according to the cppreference.com documentation for function-try blocks: a so-called function-try-block on a constructor or destructor must throw from its catch-clause or else there is an implicit rethrow after the catch-clause.
This makes perfect sense: the object A has not been properly constructed and hence is not in a state fit for use: it must throw an exception. You have to ensure whether the construction succeeded at the place where the object is constructed, i.e. in the case of your example in main().
Exception cannot be caught in constructor function-try-block.
n3376 15.2/15
The currently handled exception is rethrown if control reaches the end
of a handler of the function-try-block of a constructor or destructor.
You should catch it in object creation place.
I suggest you read the article: "GotW #66 Constructor Failures"on the site:http://gotw.ca/gotw/066.htm
I am not sure if this is a issue with the compiler or if I am doing something wrong. I am using Visual Studio 2013 compiler.
I have a class where I need to acquire significant amount of resources in my constructor initializer list most of which can throw an exception. I wrapped up the member initializer list in a function try block and caught the exception there. But my program still aborts even though the catch clause doesn't re-throw the exception. I am not allowed to post the actual code. So I have reproduced the issue with this equivalent demo code. Can someone please help me address this?
#include <iostream>
using namespace std;
class A{
public:
A() try : i{ 0 }{ throw 5; }
catch (...){ cout << "Exception" << endl; }
private:
int i;
};
int main(){
A obj;
}
On executing this code I get a windows alert "abort() has been called". So I guess the system is treating this as an uncaught exception and calling terminate().
On the other hand if I wrap the construction of the object in main() in a try-catch block then the exception is caught properly and the program terminates normally.
Can someone please tell me if I am doing something wrong here?
There's a relevant gotw
http://gotw.ca/gotw/066.htm
Basically even if you don't throw in your catch block, the exception will automatically be rethrown
If the handler body contained the statement "throw;" then the catch
block would obviously rethrow whatever exception A::A() or B::B() had
emitted. What's less obvious, but clearly stated in the standard, is
that if the catch block does not throw (either rethrow the original
exception, or throw something new), and control reaches the end of the
catch block of a constructor or destructor, then the original
exception is automatically rethrown.
This is normal behaviour according to the cppreference.com documentation for function-try blocks: a so-called function-try-block on a constructor or destructor must throw from its catch-clause or else there is an implicit rethrow after the catch-clause.
This makes perfect sense: the object A has not been properly constructed and hence is not in a state fit for use: it must throw an exception. You have to ensure whether the construction succeeded at the place where the object is constructed, i.e. in the case of your example in main().
Exception cannot be caught in constructor function-try-block.
n3376 15.2/15
The currently handled exception is rethrown if control reaches the end
of a handler of the function-try-block of a constructor or destructor.
You should catch it in object creation place.
I suggest you read the article: "GotW #66 Constructor Failures"on the site:http://gotw.ca/gotw/066.htm
Why doesn't this piece of code run without error? Isn't bad_exception supposed to be called automatically when an unexpected exception is encountered? Or is it necessary to set a handler for it?
#include <iostream>
#include <exception>
using namespace std;
class C{};
void test() throw(bad_exception)
{
throw C();
}
int main()
{
try
{
test();
} catch(bad_exception& e)
{
cout << "Caught ";
}
}
In C++03 theory:
If you throw an exception that is not in the exception specification, unexpected() gets called. If you have not set the unexpected handler via set_unexpected() this means terminate() gets called which is the case you observed. If you have set an unexpected handler that does not call terminate but throws an exception, and if that exception is not listed in your exception specification, it gets translated into bad_exception. So in order to get the expected result, call set_unexpected() first with an appropriate handler.
In C++03 practice:
Some compilers do not support exception specifications at all (other than throw()), others just don't evaluate/check them for correctness. As Herb Sutter points out, exception specifications create a clumsy "shadow type system" that is not easy to handle right (if it is possible at all). Therefore..
... in C++11:
Exception specifications are deprecated. You should rather not use them. However, there is a nothrow operator that has a slightly different functionality than throw()
PS: so why have std::bad_exception in C++03?
You hav three different regions of code:
The function you are writing an exception specification for.
The "foreign" code you are calling from that function that might or might not throw an exception that does not match you specification.
The (maybe also unknown) unexpected handler that can be anything and should either terminate/exit/abort the program or throw anything.
So if the "foreign" code throws an exception that violates your exception specification, you have three possible outcomes of that:
The handler terminates the program. There is not much you can do about that unless you set your own handler in the function.
The handler throws an exception that matches your exception specification. And all is well.
The handler throws something else. What do you want the runtime to do now? That's where bad_exception comes in: If it is in your specification, the "something else" gets translated into a bad_exception, and the program continues. If it's not, terminate gets called.
Setting your own handler inside the function disables any handler that was previously set by anyone else who just wants to use your function. He will not expect you to disable his handler. Besides, the handler is meant as a global what-happens-if policy and thus is nothing you should care about in a single function implementation.
This should call std::unexpected which by default call std::terminate() as the thrown exception isn't part of the exception specification.
(It does here with g++ on Linux, SunOracle CC on Solaris, IBM xlC on AIX BTW)
If you install an unexpected handler, it works as you expect here:
include <iostream>
#include <exception>
using namespace std;
class C{};
void myunexpected()
{
throw std::bad_exception();
}
void test() throw(std::bad_exception)
{
throw C();
}
int main()
{
try
{
set_unexpected(myunexpected);
test();
} catch(std::bad_exception& e)
{
std::cout << "Caught ";
}
}
As per [except.unexpected], when a function throws an exception not listed in its dynamic exception specification, std::unexpected() is called. According to [unexpected.handler], the default implementation of std::unexpected() simply calls std::terminate().
However, the program can install its own handler, which can (re-)throw an exception. If the exception thus thrown is not allowed by the dynamic exception specification, it can be replaced by std::bad_exception when that is allowed.
Your catch-block would only catch exceptions of the type bad_exception, or a subtype thereof. C does not meet this criterion.
Actually, this question is very similar to yours. The accepted answer explains that if your function throws an exception that does not match the specification (if there is any), then std::unexpected is called, which by default calls std::terminate.
As a follow-up to my previous question:
If I change the code as follows:
struct ExceptionBase : virtual std::exception{};
struct SomeSpecificError : virtual ExceptionBase{};
struct SomeOtherError : virtual ExceptionBase{};
void MightThrow();
void HandleException();
void ReportError();
int main()
{
try
{
MightThrow();
}
catch( ... )
{
HandleException();
}
}
void MightThrow()
{
throw SomeSpecificError();
}
void HandleException()
{
try
{
throw;
}
catch( ExceptionBase const & )
{
// common error processing
}
try
{
throw;
}
catch( SomeSpecificError const & )
{
// specific error processing
}
catch( SomeOtherError const & )
{
// other error processing
}
try
{
ReportError();
}
catch( ... )
{
}
}
void ReportError()
{
throw SomeOtherError();
}
The "last handler" for the original exception (i.e. the one in main) has not exited when the second exception is thrown, so are both exceptions active? Is the original exception still available once we leave the handler for the second exception?
C++11 (N3242):
15.1p4: The memory for the exception object is allocated in an unspecified way, except as noted in 3.7.4.1. If a
handler exits by rethrowing, control is passed to another handler for the same exception. The exception
object is destroyed after either the last remaining active handler for the exception exits by any means other
than rethrowing, or the last object of type std::exception_ptr (18.8.5) that refers to the exception object is
destroyed, whichever is later.
(std::exception_ptr is a C++11 feature, and isn't used in your example code.)
15.3p7: A handler is considered active when initialization is complete for the formal parameter (if any) of the catch clause. ... A handler
is no longer considered active when the catch clause exits or when std::unexpected() exits after being
entered due to a throw.
15.3p8: The exception with the most recently activated handler that is still active is called the currently handled exception.
15.1p8: A throw-expression with no operand rethrows the currently handled exception (15.3).
Or equivalently, I think, throw; always refers to the exception caught by the innermost catch block which is currently executing. Except that I haven't defined 'innermost' and 'executing' as carefully as the Standard defined all its terms above.
And yes, more than one exception object can be allocated at a time, and C++ is required to make sure they live long enough to do "the right thing" when you try to rethrow.
Not sure how standard it is, but if i add a throw; right before the end of HandleException and compile with g++, the resulting program tells me this:
root#xxxx [~/code]# ./a.out
terminate called after throwing an instance of 'SomeSpecificError'
what(): 17SomeSpecificError
Aborted
Note the exception type. That's the exception that was thrown in MightThrow, not the one from ReportError.
VS2010 reports a SomeSpecificError as well.
There is only one "active exception" at a time. When you throw another exception in an exception handler, in effect you are changing the type of the exception that is being propagated up the stack.
(As an aside, is all this necessary? Do you really find this code easy to read?)
[update]
As for the standard reference... ISO/IEC 14882:2003, section 15.3 [except.handle], paragraph 8 reads:
An exception is considered handled upon entry to a handler. [Note: the
stack will have been unwound at that point. ]
So another way to say this is, as soon as you enter the catch block, the original exception is no longer active.
Also, the uncaught_exception() function will return false as soon as the catch block is entered. Section 15.5.3 [except.uncaught] reads:
The function
bool uncaught_exception() throw()
returns true after completing evaluation of the object to be thrown until completing the
initialization of the exception-declaration in the matching handler
(18.6.4). This includes stack unwinding. If the exception is rethrown
(15.1), uncaught_exception() returns true from the point of rethrow
until the rethrown exception is caught again.
[update 2]
Also relevant is section 15.3 paragraph 4:
The memory for the temporary copy of the exception being thrown is
allocated in an unspecified way, except as noted in 3.7.3.1. The
temporary persists as long as there is a handler being executed for
that exception. In particular, if a handler exits by executing a
throw; statement, that passes control to another handler for the same
exception, so the temporary remains. When the last handler being
executed for the exception exits by any means other than throw; the
temporary object is destroyed and the implementation may deallocate
the memory for the temporary object; any such deallocation is done in
an unspecified way. The destruction occurs immediately after the
destruction of the object declared in the exception-declaration in the
handler.
So the original exception is destroyed as soon as the handler is exited via any means other than a naked throw;. So if you throw some other exception, that exits the handler and destroys the original exception.
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.