聚合初始化异常
Exception in aggregate initialization
在 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()" 函数创建的对象没有被释放。我只有在使用花括号进行聚合初始化时才会遇到这个问题。
当我在每个 class(A、B 和 C)上定义一个显式构造函数时,我没有遇到这个问题。
我做错了什么?
此致
您没有关联 try
/catch
因此您的程序终止。
在这种情况下不需要展开堆栈。
以下应该可以解决您可能的泄漏问题。
int main()
{
try
{
std::make_unique<C>(C{makeB(), makeListAWithException()});
}
catch (...)
{
}
}
如果你改成喜欢下面,我想问题已经解决了
std::make_unique<C>(C{makeB(),makeListAWithException()});
到
auto b = makeB();
std::make_unique<C>(C{b,makeListAWithException()});
这是 gcc bug 66139. Here is a short reproduction, courtesy of Andrzej(博客 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 (...) {}
}
这会打印:
create
它应该打印(如 clang,正确地那样):
create
destroy
在 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()" 函数创建的对象没有被释放。我只有在使用花括号进行聚合初始化时才会遇到这个问题。
当我在每个 class(A、B 和 C)上定义一个显式构造函数时,我没有遇到这个问题。
我做错了什么?
此致
您没有关联 try
/catch
因此您的程序终止。
在这种情况下不需要展开堆栈。
以下应该可以解决您可能的泄漏问题。
int main()
{
try
{
std::make_unique<C>(C{makeB(), makeListAWithException()});
}
catch (...)
{
}
}
如果你改成喜欢下面,我想问题已经解决了
std::make_unique<C>(C{makeB(),makeListAWithException()});
到
auto b = makeB();
std::make_unique<C>(C{b,makeListAWithException()});
这是 gcc bug 66139. Here is a short reproduction, courtesy of Andrzej(博客 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 (...) {} }
这会打印:
create
它应该打印(如 clang,正确地那样):
create
destroy