簡體   English   中英

在n元樹中創建/訪問節點時發生內存泄漏

[英]Memory leak when creating/accessing nodes in n-ary tree

我從以下代碼獲取內存泄漏:

struct Node {
    Node *children[20];
    int value;

    Node();
    ~Node();
};

Node::Node() {
    for(int i=0; i<20; i++) {
        children[i] = NULL;
    }
}

void Node::insert(int x) {
    Node *n = this;
    for(int i=0; i<20; i++) {
        if(n->children[i] == NULL) {
            n->children[i] = new Node();
            n->children[i]->value = x;
        }
        n = n->children[i];
    }
}  

檢查Valgrind,顯然我從這條線泄漏:

n->children[i] = new Node();

這是使用構造函數的錯誤方法嗎?
還是Valgrind支票有誤導性?

Valgrind錯誤消息:

505 (448 direct, 57 indirect) bytes in 2 blocks are definitely lost in loss record 2 of 3
  at 0x4C2B1C7: operator new(unsigned long)
  by 0x401A4F: Node::insert
  by 0x4015FA: main

LEAK SUMMARY:
  definitely lost: 448 bytes in 2 blocks
  indirectly lost: 57 bytes in 2 blocks
    possibly lost: 0 bytes in 0 blocks
  still reachable: 72,704 bytes in 1 blocks
       suppressed: 0 bytes in 0 blocks

ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 2 from 2)  

我擁有的析構函數:

Node::~Node() {
    for(int i=0; i<20; i++) {
        delete children[i];
        children[i] = NULL;
    }
}

在主要方面:

int main() {
    Node *n = new Node();

    .
    .
    .

    delete n;
    n = NULL;

    return 0;
}

您沒有刪除孩子。 正如Axel回答的那樣,您應該在析構函數中添加一個刪除。 或更妙的是,使用unique_ptr數組,該數組將在節點超出范圍時銷毀節點。

您永遠不會刪除子指針。

您應該刪除Node類析構函數中子數組的每個分配指針。

像那樣 :

Node::~Node()
{
    for (int i = 0; i < 20; ++i)
    {
        delete children[i];
    }
}

此外,如果還有其他方法可以替換子數組中的指針,則必須先刪除之前的指針,然后再執行以下操作:

...
delete n->children[i];
n->children[i] = new Node();
...

要么

...
delete n->children[i];
n->children[i] = p;  // where p is a pointer of Node
...

有關信息,您必須調用delete來銷毀和釋放在堆上構造的每個對象(使用new )。

您也可以使用smartpointer來避免管理兒童成員的破壞。

我看到一個新的,但沒有刪除的指針,也沒有智能指針。 這意味着您無需分配內存就可以分配內存。 (至少您沒有向我們展示Node的析構函數應該在哪里進行。)

除此之外,您的代碼還有一些缺陷:

  • 您對n的使用看起來可疑,目前尚不清楚它的作用是正確的還是僅僅是錯誤。 您可能希望至少通過注釋來澄清,或者使用其他功能和有意義的名稱來更好地加以說明。
  • 一旦找到NULL指針並用新的Node充滿整個數組,您就不會停止,這意味着您可以一次成功插入exaclty
  • 您默認構造一個節點並立即為其分配一個值-可能您應該編寫一個相應的構造器。

使用智能指針分配內存:

struct Node {
    unique_ptr<Node> children[20]; //consider switching to std::array
    int value;

    // no destructor needed, because unique_ptr takes care of itself    
    Node (int newValue);
    void insert(int valueToInsert);
};


void Node::insert(int valueToInsert) {
    auto freeSpot = //find the point where you want to insert the new node
    if ( /*freeSpot is a valid location*/ )
        *freeSpot = make_unique<Node>(x);
}  

Node::Node(int newValue) 
  : value(newValue)
{}

那將是您可以做的第一個重構

暫無
暫無

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

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