防止内存泄漏c ++

prevent memory leak c++

本问题已经有最佳答案,请猛点这里访问。

如何防止下面代码中的内存泄漏?我在返回语句之前添加了"删除sentinel"。但是如何处理这两条线d->next = new ListNode(sum % 10)d->next = new ListNode(1)的内存泄漏

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        ListNode* c1 = l1;
        ListNode* c2 = l2;
        ListNode* sentinel = new ListNode(0);
        ListNode* d = sentinel;
        int sum = 0;

        while(c1 != NULL || c2 != NULL) {
            sum /=10;

            if(c1 != NULL){
                sum += c1->val;
                c1 = c1->next;
            }

            if(c2!= NULL){
                sum += c2->val;
                c2 = c2->next;
            }

            d->next = new ListNode(sum % 10);
            d = d->next;
        }    

        if(sum /10 == 1){
                d->next = new ListNode(1);
        }

        return sentinel->next;
    }
};


你的代码真的很混乱…不是因为算法很复杂,而是因为您使用了多个变量来指向同一个对象。为什么有这么多未使用的变量?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2)
{
    ListNode* sentinel = new ListNode(0);
    listNode* d = sentinel;
    int sum = 0;
    while (l1 != NULL || l2 != NULL) // use pointers l1 and l2, since passed by value.
    {
        if (l1 != NULL)
        {
            sum += l1->val;
            l1 = l1->next;
        }

        if (l2 != NULL)
        {
            sum += l2->val;
            l2 = l2->next;
        }

        d->next = new ListNode(sum % 10);
        sum /= 10;
        d = d->next;
    }    

    if (sum)
    {
        d->next = new ListNode(sum);
    }

    // And this is where one of your memory leaks was...
    if (sentinel->next)
    {
        d = sentinel->next;      // delete useless sentinel.
        sentinel->next = NULL;   // important !  see ~ListNode()
        delete sentinel;
        sentinel = d;
    }
    return sentinel;   // and not result->next.
}

为了避免列表泄漏,您需要编写一个适当的列表析构函数来释放子节点和其他依赖资源(如果有的话)。这是C++中经常出现的一个主题。

1
2
3
4
5
6
7
8
9
10
11
ListNode::~ListNode()
{
    // never destroy lists recursively !!  Destroying a large list
    // that way could bust the stack, hence this odd looking loop.
    for (ListNode * p = next, * q = NULL; p != NULL; p = q)
    {
        q = p->next;
        p->next = NULL;   // <-- avoids recursion.
        delete p;
    }
}

有一个简单的答案-当前代码有一个泄漏-sentinel,所有其他分配的节点都不会泄漏-因为它们仍然可以通过返回的pointer sentinel->next访问

所以修复漏洞的简短版本将会改变

1
    return sentinel->next;

具有

1
2
3
    d = sentinel->next;
    delete sentinel;
    return d;

较长的版本需要将原始指针的用法更改为智能指针std::unique_ptr,在这种情况下,看起来像是选择的指针。但对于整个程序来说,这不仅仅是一个函数。

实际上,正如事后所想,更理想的解决方案是使用std::forward_列表而不是自制列表。


不要使用原始指针。请参阅C++核心指南(C++中最重要的一些领导者的最新指南)。