簡體   English   中英

將多態unique_ptr作為參數傳遞時發生內存泄漏

[英]Memory leak when passing polymorphic unique_ptr as argument

編輯:對於閱讀此問題以供將來使用的任何人:該錯誤無論如何都與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()時已經構造了運算符。

你不告訴我們的代碼的關鍵件-的聲明Node ,特別是它的析構函數,部分NodeSpace ,特別是如何刪除Node S,等等。但是從您的評論“無論是節點,也算有任何析構函數和復制/ move構造函數/賦值運算符”,看來這就是問題所在。

如果您通過Node *unique_ptr<Node>維護Operator所有權,即,如果您通過Node *刪除任何派生對象,則Node 必須具有虛擬析構函數。 如果您未聲明並定義一個,則不會。

雖然結果的行為是不確定的,但結果通常是未調用派生類的成員的析構函數。 符合您的錯誤消息。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM