recently at work i had a problem with resource leak in one of my tests. it took me a while to notice that gcc does not generate proper code, if exception is triggered, while doing bracket-initialization of an object. problem is nicely illustrated in a code below:
#include <iostream> using namespace std; struct Data { Data(int) { throw 42; } Data(void) { cout << __PRETTY_FUNCTION__ << endl; } Data(Data const&) { cout << __PRETTY_FUNCTION__ << endl; } Data(Data&&) { cout << __PRETTY_FUNCTION__ << endl; } ~Data(void) { cout << __PRETTY_FUNCTION__ << endl; } }; struct More { Data a_; Data b_; }; More foo(void) { return { Data{}, Data{1} }; // <-- here is the problem } int main(void) { try { foo(); } catch(...) { cerr << "exception" << endl; } }
while constructing object More, in function foo(), if second parameter throws, previous object is never destroyed, so the output is:
Data::Data() exception
instead of (clang gives valid result, btw):
Data::Data() Data::~Data() exception
simply removing argument from c-tor of a second object (i.e. no exception) outputs proper order:
Data::Data() Data::Data() Data::~Data() Data::~Data()
i've discovered this issue in GCC 4.7, confirmed in 4.8 and was (in a way) happy to file a report… when i discovered it has already been reported. almost a year ago. to make it worse, GCC 4.9 has just been released and the bug is still in “new” state (not even assigned). haven't tested with 4.9, though most likely it still won't work… bad news. :(