0

NOTE: I am using gcc 4.4.7 on redhat linux 6.3. The question in below example is about what GCC does to first exception thrown from A::doSomething() and NOT about whether exceptions should be thrown from destructor.

In the following code, the function A::doSomething() exits with 2 logic_error exceptions. The second logic_error from the destructor ~A() seem to be overwriting the logic_error from A::doSomething(). The output from the program is given below.

My question is what happened to logic_error thrown by A::doSomething(). Is there a way to recover it?

#include <iostream>
#include <stdexcept>

#include <sstream>

using namespace std;

class A
{
public:
A(int i):x(i) {};
void doSomething();

~A() {
    cout << "Destroying " << x << endl;
    stringstream sstr;
    sstr << "logic error from destructor of " << x << " ";
    throw logic_error(sstr.str());
    }

private:
int x;
};

void A::doSomething()
{
A(2);
throw logic_error("from doSomething");
}


int main()
{

A a(1);
try
{
    a.doSomething();
}
catch(logic_error & e)
{
    cout << e.what() << endl;
}

return 0;
}

Output is:

Destroying 2
logic error from destructor of 2
Destroying 1
terminate called after throwing an instance of 'std::logic_error'
what():  logic error from destructor of 1
Aborted (core dumped)
Jimm
  • 8,165
  • 16
  • 69
  • 118

1 Answers1

1

EDIT: experimenting on http://www.compileonline.com I also find the observed behavior odd. It looks as if terminate() would be called on a different thread or async, while the main thread executed ahead, even destroying A(1), before the system noticed it should stop.

re-reading the C++03 it still states the same, by 15.5.1p1b3 terminate must be called, and by p2 no further anything is allowed. gcc behavior appear nonconforming here.

on http://coliru.stacked-crooked.com/ newer gcc output is:

Destroying 2
terminate called after throwing an instance of 'std::logic_error'
  what():  logic error from destructor of 2 

This is the expected one (without the last two lines but we can consider it extra info after the terminate() call).


The theory for conforming implementation:

Read GOTW#47 and SO thread on what happens if you write code like that.

As summary: the language rules are that if an exception is successfully thrown (it was copied and stack unwinding started), and before it is caught another exception is thrown, terminate() is called. As terminating in unlikely what you want, consider rearranging the code to avoid this problem.

Community
  • 1
  • 1
Balog Pal
  • 16,195
  • 2
  • 23
  • 37