聚合初始化中的异常

时间:2018-07-10 07:53:32

标签: c++ exception c++14 aggregate valgrind

在C ++ 14(gcc 6.3)中,我有以下代码:

#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()});
}

在运行valgrind时,我发生了内存泄漏:似乎没有释放由“ makeB()”函数创建的对象。仅在将聚合初始化与花括号一起使用时,我才遇到这个问题。

当我在每个类(A,B和C)上定义一个显式构造函数时,我没有这个问题。

我在做什么错了?

最诚挚的问候

3 个答案:

答案 0 :(得分:5)

这是gcc bug 66139。这是Andrzej的简短复制(在博客文章中有更详尽的描述):

#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 (...) {}
}

此打印:

create

它应该打印(正确地说是clang):

create
destroy    

答案 1 :(得分:2)

您没有关联try / catch,因此您的程序终止了。

在这种情况下,不需要

堆栈展开。

以下应该解决您可能的泄漏。

int main()
{
    try
    {
        std::make_unique<C>(C{makeB(), makeListAWithException()});
    }
    catch (...)
    {
    }
}

答案 2 :(得分:0)

如果您更改为如下所示,我认为问题已解决

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

auto b = makeB();
std::make_unique<C>(C{b,makeListAWithException()});