This question already has answers here:
An exception gets thrown twice from a constructor with a function-try-block
(3 answers)
Closed 8 years ago.
I am new to C++ exception handling. The rule in my mind is that,
If no handler of an exception is found in the call chain (the stack of function calling), then the terminate function is called.
A handler is a catch {} block.
However, I cannot understand the behaviour of the following.
#include <iostream>
#include <exception>
using namespace std;
struct X {
X() try { throw exception(); }
catch (exception &e) {
cout << "Exception caught in constructor!" << endl;
}
};
int main() {
try {
throw exception();
}
catch (exception &e) {
cout << "Exception caught in function." << endl;
}
cout << "After Exception being caught in function" << endl;
try {
X x;
}
catch (exception &e) {
cout << "Why exception is caught again!" << endl;
}
return 0;
}
The output is
Exception caught in function.
After Exception being caught in function
Exception caught in constructor!
Why exception is caught again!
Question 1: It seems that the exception thrown in the constructor of X is caught (or. handled) twice. Or why the catch{} block following the constructor not counted as a handler for the exception in the constructor?
If I do not put X x; in the try{} block and catch it in the main(), the output is:
Exception caught in function.
After Exception being caught in function
Exception caught in constructor!
terminate called after throwing an instance of 'std::exception'
what(): std::exception
Aborted (core dumped)
Question 2: Is the default terminate() function called when we do not have X x; in a try block?
With:
X() try { throw exception(); }
catch (exception &e) {
cout << "Exception caught in constructor!" << endl;
}
X object is not completely constructed and so the catch cannot ignore the exception and should re-throw it.
IMO, it is more clear when X has a member which throw... (X() try : member(0) {} catch(exception&) {} ).
Note that you may use a normal try catch inside the constructor block:
X() {
try { throw exception(); }
catch (exception &e) {
cout << "Exception caught in constructor!" << endl;
}
}
which is more natural.
You have two exceptions.
struct X {
X() try { throw exception(); }
catch (exception &e) {
cout << "Exception caught in constructor!" << endl;
}
};
After an exception you will handle it in the constructor. BUT you didn't construct
the object yet and you have no object in the caller's side. The caller
should handle an un-constructed object situation. †
Second question, yes. Per [except.terminate] in the standard. It causes to invoke std::terminate.
Related
When an exception is thrown from the class constructor, the program crashes. While running in debug mode I get the following error "Unhandled exception at 0x74A2DB18 in VirtualCtor.exe: Microsoft C++ exception: [rethrow] at memory location 0x00000000." It crashes in release mode too. I understand that this because throw does not find the exact catch handler and std::terminate() is called. But, I had the understanding that catch(...) should handle this. Can someone let me know the exact handler that I need to use with catch?
#include<iostream>
#include<exception>
using namespace std;
class MyClass
{
public:
MyClass() { cout << "Default Ctor" << endl;
throw; //runtime exception.
}
~MyClass()
{
cout << "Destructor called" << endl;
}
};
int main()
{
MyClass*vpt = nullptr;
try {
vpt = new MyClass;
}
catch (...) {
delete vpt;
cout << "Exception"<< endl;
}
return 0;
}
Changing code throw bad_alloc(); catches the exception and the code crashes no longer, but I need to understand what happens with just calling throw from function/constructor?
Thanks.
You're not throwing an exception. You're just writing throw, which re-throws an exception already thrown. In this case, there isn't one, so your program has undefined behaviour. Hence the crash.
If you want to throw something, you actually have to throw something!
MyClass()
{
cout << "Default Ctor" << endl;
throw std::runtime_exception("Testing exception handling");
}
#include <iostream>
using namespace std;
class Cls
{
public:
~Cls()
{
throw "exp";
}
};
int main()
{
try
{
Cls c;
throw "exp";
}
catch (...)
{
cout << "Why this doesn't call" << endl;
}
}
When I execute this code, it doesn't goes in catch block. And give following exception,
But, when I run this code with little modification, it goes to catch block.
int main()
{
try
{
throw "exp";
throw "exp";
}
catch (...)
{
cout << "Why this doesn't call" << endl;
}
}
Output:
Both the above code throws 2 exception, then why Compiler is biased in destructor's case?
In the first case you first throw from the try block and then the stack unwinding throws from Cls's destructor. So you have two exceptions to be handled. C++ handles this situation by calling terminate.
Because of the peculiarity of throwing from destructors, C++11 defines that all destructors are noexcept by default. Then even if there is no other exception to be handled, the exception from a destructor will cause terminate to be called.
The second case is OK because as soon as you throw the first exception try block is left and the exception is handled in the catch block.
I have the following C++ code and it gives me a surprise.
The problem is that if I throw something except re-throw inside the catch block,
the program will be terminated by calling abort and give the error message in GCC4,
"terminate called after throwing an instance of 'int'".
If I just use "throw;" to re-throw inside the catch block, everything will be fine.
#include <iostream>
#include <exception>
#include <stdexcept>
using namespace std;
int main()
{
try{
throw std::string("first throw");
}
catch(std::string &x){
try{
std::cout << x << std::endl;
// throw; // if I use this line, all is fine.
throw int(2); // but if I use this line, it causes Abort() to be called
}
catch (int &k){
throw;
}
catch(...)
{
cout << "all handled here!"<< endl;
}
}
catch(...){
std::cout<< "never printed" << endl;
}
}
If you throw an int, then it won't be handled; it will be caught by the inner catch (int &k) handler, which rethrows it; and there is no outer handler to catch the rethrown exception, since you're already in an outer catch block. So in this case, terminate is called due to an unhandled exception.
If you rethrow the string, then it's caught by the inner catch(...) handler; this doesn't rethrow, so the exception has then been handled.
You throw is not inside any try handler thus it leads to abort being called.
Here is your code with the indentation cleaned up a bit and some comments inline:
#include <iostream>
#include <exception>
#include <stdexcept>
using namespace std;
int main()
{
try {
throw std::string("first throw");
}
catch (std::string &x) {
try {
std::cout << x << std::endl;
// throw; // if I use this line, all is fine.
throw int(2); // but if I use this line, it causes Abort() to be called
}
catch (int &k) {
// Catches and rethrows exception. Not inside a try thus leads to abort.
throw;
}
catch (...) {
// Will handle the case where the string is rethrown instead. No abort.
cout << "all handled here!"<< endl;
}
}
catch (...) {
std::cout<< "never printed" << endl;
}
}
This isn't a question on whether it's safe to throw an exception from a destructor.
http://www.parashift.com/c++-faq-lite/exceptions.html#faq-17.9 states:
"During stack unwinding, all the local objects in all those stack frames are destructed. If one of those destructors throws an exception (say it throws a Bar object), the C++ runtime system is in a no-win situation: should it ignore the Bar and end up in the } catch (Foo e) { where it was originally headed? Should it ignore the Foo and look for a } catch (Bar e) { handler? There is no good answer — either choice loses information."
IE: if during stack unwinding another exception is thrown, then the runtime system is in a no-win situation because the catch handler to 'look for' is ambiguous.
Is there an 'exception' to the above, when the exception that is thrown during stack unwinding itself is in a try/catch block? In this case there is no ambiguity:
#include <iostream>
using namespace std;
class Component
{
public:
~Component()
{
cout << "In component destructor" << endl;
try
{
throw 1;
}
catch (...)
{
cout << "Caught exception in component destructor" << endl;
}
}
};
class Container
{
public:
~Container()
{
cout << "In container destructor" << endl;
Component component;
}
}
;
int main()
{
try
{
Container cont;
throw 'a';
}
catch (...)
{
cout << "Caught main exception ok" << endl;
}
return 0;
}
The following implies it, but I was wondering if anyone knew of the relevant C++ standard sections.
http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8a.doc%2Flanguage%2Fref%2Fcplr155.htm
"If during stack unwinding a destructor throws an exception and that exception is not handled, the terminate() function is called. The following example demonstrates this:"
Your Component destructor is safe. The rule you're quoting only applies if the exception is thrown out of the destructor (i.e., to the destructor's caller.)
EDIT: Here's one relevant quote from the standard (emphasis added)
Note: If a destructor called during
stack unwinding exits with an
exception, std::terminate is called
(15.5.1).
Consider the following program
#include <iostream>
#include<cstdlib>
using namespace std;
class E {
public:
const char* error;
E(const char* arg) : error(arg) { }
};
void my_terminate() {
cout << "Call to my_terminate" << endl;
}
struct A {
A() { cout << "In constructor of A" << endl; }
~A(){
cout << "In destructor of A" << endl;
throw E("Exception thrown in ~A()");
}
};
struct B {
B() { cout << "In constructor of B" << endl; }
~B() { cout << "In destructor of B" << endl; }
};
int main() {
set_terminate(my_terminate);
try {
cout << "In try block" << endl;
A a;
B b;
throw E("Exception thrown in try block of main()"); // Line 36
}
catch (E& e) {
cout << "Exception: " << e.error << endl;
}
catch (...) {
cout << "Some exception caught in main()" << endl;
}
cout << "Resume execution of main()" << endl;
}
Output:
In try block
In constructor of A
In constructor of B
In destructor of B
In destructor of A
Call to my_terminate
Disallowed system call: SYS_kill
In line 36 an exception is thrown from the try block in main. Now why is this exception not caught by the handler?
Rather the 'stack unwinding' process continues.The destructor of A throws an exception too which is again not caught by any handler,instead a call to my_terminate is made, why?
Why is the handler not called in the two cases?
The C++ rule is that you must never throw an exception from a destructor that is being called during the "stack unwinding" process of another exception.
You throw an exception in A's destructor, which is something you are not supposed to do.
When you throw the original E temporary from the try block in main, the runtime implementation constructs an exception object of type E and searches for the first catch block that can handle the exception. In this case, this is the immediately following catch (E& e) block.
When the implementation finds the correct catch to handle the exception, it then destroys all automatic variables which must go out of scope by moving out of the scope where the throw occurred to the scope in which the catch resides.
In this case the objects a and b which are local to the catch block go out of scope, so must be destroyed (in the reverse order that they were created). However, destroying a causes another exception to be thrown. Because the implementation already has an uncaught exception and has already chosen a catch handler for that exception which it is trying to reach, there is no mechanism to handle this new exception. The rule in this case is that std::terminate, and in your case your terminate handler, is called immediately.
You should note that your my_terminate function is not a conforming terminate_handler, as a terminate_handler must not return and must terminate the program execution (i.e. must not throw either). Yours returns implicitly.
set_terminate
function installs term_func as the function called by terminate. set_terminate is used with C++ exception handling and may be called at any point in your program before the exception is thrown. terminate calls abort by default. You can change this default by writing your own termination function and calling set_terminate with the name of your function as its argument. terminate calls the last function given as an argument to set_terminate. After performing any desired cleanup tasks,
term_func should exit the program.
If it does not exit (if it returns to its caller), abort is called.
my_terminate() should look like :
void my_terminate()
{
cout << "Call to my_terminate" << endl;
*
*
*
exit(-1);
}
In section 15.2 of my draft standard it states:
3 The process of calling destructors
for automatic objects constructed on
the path from a try block to a
throw-expression is called “stack
unwinding.” [ Note: If a destructor
called during stack unwinding exits
with an exception, std::terminate is
called (15.5.1). So destructors should
generally catch exceptions and not let
them propagate out of the destructor.
—end note ]
They have defined "stack unwinding" broadly enough that it seems to cover this case, even if it is all happening within one function. I guess it's somewhat clear that implementations expect destructors not to try and propagate exceptions outward.
Here is the problem. Your A's destructor throws, which is a bad thing. Re-throwing exceptions, or throwing a new exception in an exception handler is kosher because the stack-unwinding is well-behaved. In that case, only one exception is alive at the current stack frame. When a destructor throws an exception during the stack unwinding process however, two exceptions are alive the same stack frame, i.e they unwind the stack on the same level. In your case, that's two E objects. So which one does one choose to follow? You cannot follow both, so the standard says that terminate() will be called. You can make the exception system use your custom terminate routine by passing one with std::set_terminate() from the header <exception>.
You seem to think that your std::terminate() handler can resume your program by returning, but that's undefined behavior.
If you absolutely positively need to throw from a destructor and can't contain it with an exception handler inside the destructor itself, here is a workaround:
The function uncaught_exception() from the header <exception> returns true if an exception has been thrown, but not yet caught. If it returns true, that means that the process is in the middle of a stack unwinding, unwinding the stack and calling destructors until it finds a proper exception handler. Use the function inside destructors which throw, so that they only throw when a stack unwinding is not happening.
Here's an example on how to use uncaught_exception() (Though, it's an extremely bad idea):
#include <iostream>
#include <exception>
#include <stdexcept>
#include <sstream>
#include <cstdlib>
void termhandler()
{
std::cout << "Inside terminate()" << std::endl;
abort();
}
class Foo
{
public:
Foo(int val) : i(val){ std::cout << "Created Foo object " << i << std::endl; }
~Foo()
{
if(std::uncaught_exception()){
std::cout << "~Foo::Foo() object " << i << " : " << "Stack unwinding in progress. Can't throw!" << std::endl;
} else {
std::cout << "~Foo::Foo() object " << i << " : " << "Throwing test exception." << std::endl;
std::ostringstream strm;
strm << i;
std::runtime_error e("Exception from ~Foo::Foo() object " + strm.str());
throw e;
}
}
int i;
};
int main()
{
try {
std::set_terminate(termhandler);
Foo A(1);
Foo B(2);
} catch(std::exception& e){
std::cout << "Caught exception in main() : " << e.what() << std::endl;
}
}
Which gives the following output:
Created Foo object 1
Created Foo object 2
~Foo::Foo() object 2 : Throwing test exception.
~Foo::Foo() object 1 : Stack unwinding in progress. Can't throw!
Caught exception in main() : Exception from ~Foo::Foo() object 2