编辑:对于任何阅读此问题以备将来使用的人:该错误与 unique_ptr 无关。正如 JoergB 在他的回答中公正地说的那样,这只是我忘记基类的虚拟析构函数的错误。
在偶尔的运行时崩溃之后,我认为我的代码正遭受严重的内存泄漏炎。我用 Valgrind 运行我的程序,医生似乎同意:字节肯定会丢失。不过,我终其一生都无法弄清楚哪里出了问题。
我设法将泄漏归结为以下三行:
std::unique_ptr<Operator> pointer(new Operator{"left", "right"});
NodeSpace space; // The node space takes ownership over the operator
// When I comment out the following line, Valgrind reports nothing:
space.setNode("key", move(pointer));
在第一行unique_pointer
创建了一个类的实例Operator
。内部Operator
看起来像这样:
class Operator : public Node {
public:
Operator(std::initializer_list<std::string> input_keys) {
input_nodes_.reserve(input_keys.size());
for_each(begin(input_keys), end(input_keys), [this](const string& key) {
input_nodes_[key] = nullptr;
});
}
// ...
private:
std::unordered_map<std::string, Node*> input_nodes_;
};
我将unique_ptr
r 值引用传递给以下函数:
void NodeSpace::setNode(const std::string& key, std::unique_ptr<Node> node);
因为节点空间接管了传入节点的所有权,所以它采用unique_ptr
按值(移动语义)。在内部它将指针存储在一个 中std::map
,但即使函数体被注释掉,内存泄漏仍然会发生(这让我相信问题是node
函数调用的参数)。
有人远程知道问题出在哪里吗?
旁注:我没有使用shared_ptr
,因为节点可以以循环方式相互引用。weak_ptr
可能是一种选择,但是通过系统的构建,当其拥有的节点空间不再存在时,节点就不可能存在。
Valgrind 输出:
==83791== 112 (16 direct, 96 indirect) bytes in 1 blocks are definitely lost in loss record 606 of 794
==83791== at 0x100060ABD: malloc (vg_replace_malloc.c:274)
==83791== by 0x1000C9147: operator new(unsigned long) (in /usr/lib/libc++.1.dylib)
==83791== by 0x10000CB0F: std::__1::__hash_table<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, mimi::Node*>, std::__1::__unordered_map_hasher<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, mimi::Node*, std::__1::hash<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, true>, std::__1::__unordered_map_equal<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, mimi::Node*, std::__1::equal_to<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, true>, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, mimi::Node*> > >::__rehash(unsigned long) (in ./test/mimi)
==83791== by 0x10000C684: std::__1::__hash_table<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, mimi::Node*>, std::__1::__unordered_map_hasher<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, mimi::Node*, std::__1::hash<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, true>, std::__1::__unordered_map_equal<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, mimi::Node*, std::__1::equal_to<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, true>, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, mimi::Node*> > >::rehash(unsigned long) (in ./test/mimi)
==83791== by 0x100005D5A: mimi::Operator::Operator(std::initializer_list<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >) (in ./test/mimi)
==83791== by 0x100005984: mimi::Operator::Operator(std::initializer_list<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >) (in ./test/mimi)
==83791== by 0x10002E940: main (in ./test/mimi)
我也不明白为什么 Valgrind 似乎告诉我泄漏发生在Operator
构造函数中,即使在调用时操作符已经被构造NodeSpace::setNode()
。