Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Exception in aggregate initialization

In C++14 (gcc 6.3) I have the following code:

#include <memory>
#include <vector>
#include <stdexcept>

struct A
{
    int a1;
    int a2;
};

struct B
{
    int b1;
    std::shared_ptr< std::vector<A> > Alist;        
};

struct C
{
    std::shared_ptr<B> b;
    std::shared_ptr< std::vector<A> > Alist;        
};    

std::shared_ptr< std::vector<A> > makeListA()
{
    std::vector<A> toto = {{0,1}, {2,3}};
    return std::make_shared< std::vector<A> >(toto);
}

std::shared_ptr< std::vector<A> > makeListAWithException()
{
    throw std::out_of_range("My exception");
}

std::shared_ptr<B> makeB()
{
    return std::make_shared<B>(B{0, makeListA()});
}

main()
{
    std::make_unique<C>(C{makeB(),makeListAWithException()});
}

When running valgrind i have a memory leak : it looks like the objects created by "makeB()" function were not freed. I had this problem only when using aggregate initialization with curly braces.

When I define an explicit constructor on each class (A, B and C), I don't have this issue.

What am I doing wrong ?

Best regards

like image 460
Lateef Avatar asked Jul 10 '18 07:07

Lateef


1 Answers

This is gcc bug 66139. Here is a short reproduction, courtesy of Andrzej (with a more thorough description available in the blog post):

#include <cstdio>
#include <stdexcept>

struct Resource
{
  explicit Resource(int) { std::puts("create"); }
  Resource(Resource const&) { std::puts("create"); }
  ~Resource() { std::puts("destroy"); }
};

Resource make_1() { return Resource(1); }
Resource make_2() { throw std::runtime_error("failed"); }

struct User 
{
  Resource r1;
  Resource r2;
};

void process (User) {}

int main()
{
  try {
    process({make_1(), make_2()});
  }
  catch (...) {}
}

This prints:

create

It should print (as clang, correctly, does):

create
destroy    
like image 160
Barry Avatar answered Sep 29 '22 07:09

Barry