I've got a test case where I have a class with 3 subobjects (A, B and C), and the 2nd subobject B throws an exception during construction. As I understand C++, the compiler should rewind the construction of the big class and destroy the 1st object A, but not the 2nd (B) or 3rd (C) objects.
What I see is that if I use "In-class initialization" of the first object A, then instead of the first object A getting destroyed, the 3rd object C gets destroyed. Of course it is VERY BAD to destroy an object that has not been constructed! If, for example, C was a std:unique_ptr<T>, it will probably signal a segmentation violation when it tries to free a garbage pointer.
If I use old school "member initialization", then this problem doesn't happen.
I don't see this with gcc 4.8
Here's the code. The class D exposes the bug. The class E should be identically functionally, but it does not expose the bug.
#include <iostream>
using namespace std;
struct A {
A(const string& x) : x_(x) { cout << "A::A()" << (void*)this <<endl; }
~A() { cout << "A::~A() " << (void*)this<< endl;}
string x_;
};
struct B {
B(const A& a) { cout << "B::B()" << endl; try { throw "dead";} catch(...) { throw;} }
~B() { cout << "B::~B()" << endl;}
};
struct C {
C() { cout << "C::C()" << endl; }
~C() { cout << "C::~C()" << endl;}
};
struct D {
A a{"foo"}; // "new school In-class initialization"
B b{a};
C c;
D() { cout <<"D::D()" << endl; }
~D() { cout <<"D::~D()" << endl; }
};
struct E {
A a;
B b;
C c;
E()
:a{"foo"} // "old school member initialization"
,b(a)
{ cout <<"E::E()" << endl; }
~E() { cout <<"E::~E()" << endl; }
};
int main()
{
try {
D d;
}
catch(...)
{
cout << "got exception" << endl;
}
try {
E e;
}
catch(...)
{
cout << "got exception" << endl;
}
return 0;
}
Here is the output. I except to see A constructed, B partially constructed then throws, then A destroyed, but that is not what I see for the D case.
$ icpc -std=c++11 test.cpp
$ ./a.out
A::A()0x7fffe0a5ee90
B::B()
C::~C()
got exception
A::A()0x7fffe0a5eea0
B::B()
A::~A() 0x7fffe0a5eea0
got exception
Aucun commentaire:
Enregistrer un commentaire