【问题标题】:Why is there a memory leak in my program?为什么我的程序中存在内存泄漏?
【发布时间】:2021-07-13 14:21:23
【问题描述】:

我已经实现了一个单链表,其中有一个SinglyList 类,struct node、node *head 作为该类的私有成员;并写了一个析构函数来删除它。我使用 CRT 库使用 _CrtDumpMemoryLeaks() 方法检查内存泄漏。当我调试代码时,它在调试控制台中显示发现内存泄漏,这很奇怪,因为我写了一个析构函数来删除它。

这显示在调试控制台中:-

这是节点类:-

struct node 
{
    int data = NULL;
    node*next = NULL;
};

这是析构函数:-

SinglyList::~SinglyList()
{
    node*curr = head,*next;
    while(curr != NULL)
    {
        next = curr->next;
        delete curr;
        curr = next;
    }
}

我不明白,删除所有节点时怎么会出现内存泄漏,请帮忙。

编辑:

SinglyList.hpp:-

#pragma once 
#include<iostream>

class SinglyList
{
private:
    struct node 
    {
        int data = NULL;
        node*next = NULL;
    };
    node*head;
public:
    SinglyList();
    void Append(const int&);
    void Prepend(const int&);
    void Print();
    void Insert(const int&,const int&);
    void Delete(const int&);
    void Reverse();
    bool isEmpty();
    ~SinglyList();
};

SinglyList::SinglyList()
{
    head = NULL;
}

SinglyList::~SinglyList()
{
    node*curr = head,*next;
    while(curr != NULL)
    {
        next = curr->next;
        delete curr;
        curr = next;
    }
}

void SinglyList::Append(const int&data)
{
    node*n = new node{data};
    if(!head)
    {
        head = n;
        return;
    }
    node*ptr = head;
    while(ptr->next)
        ptr = ptr->next;
    ptr->next = n;
}

void SinglyList::Prepend(const int&data)
{
    node*n = new node{data};
    if(!head)
    {
        head = n;
        return;
    }
    n->next = head;
    head = n;
}

void SinglyList::Print()
{
    if(!head)
        return;
    node*ptr = head;
    while(ptr)
    {
        std::cout<<ptr->data<<' ';
        ptr = ptr->next;
    }
    std::cout<<std::endl;
}

void SinglyList::Insert(const int&pos,const int&data)
{
    if(pos == 1)
    {
        Prepend(data);
        return;
    }
    node*n = new node{data};
    node*ptr = head;
    for(int i = 1;i!=pos-1;i++)
        ptr = ptr->next;
    n->next = ptr->next;
    ptr->next = n;
}

void SinglyList::Delete(const int&pos)
{
    if(!head)
        return;
    node*ptr = head;
    if(pos == 1)
    {
        head= head->next;
        delete ptr;
        return;
    }
    for(int i = 1;i!= pos-1;i++)
        ptr = ptr->next;
    node*temp = ptr->next;
    ptr->next = temp->next;
    delete temp;
}

void SinglyList::Reverse()
{
    if(!head)
        return;
    node*curr = head,*prev = NULL,*next = NULL;
    while(curr)
    {
        next = curr->next;
        curr->next = prev;
        prev = curr;
        curr = next;
    }
    head = prev;
}

bool SinglyList::isEmpty()
{
    return (!head);
}

main.cpp:-

#include"SinglyList.hpp"
#include<crtdbg.h>

int main()
{
    SinglyList nums{};
    nums.Append(10);
    nums.Append(20);
    nums.Append(30);
    _CrtDumpMemoryLeaks();
    return 0;
}

【问题讨论】:

  • 析构函数真的被调用了吗?
  • 您的列表中是否正好有 3 个节点?
  • @Divij Manchanda 提供一个演示问题的最小完整程序。
  • 注意到泄露的项目 177 似乎是指向泄露项目 178 的节点,泄露项目 178 似乎是指向泄露项目 179 的节点,泄露项目是指向 NULL 的节点。 @500-InternalServerError 的问题值得关注。
  • 请按照弗拉德的要求显示minimal reproducible example。如果您在准备问题时没有回答自己的问题 - 这将有助于我们帮助您更快地找到问题。

标签: c++ memory-leaks linked-list c++17


【解决方案1】:

在列表被删除之前打印泄漏。试试这个:

#include"SinglyList.hpp"
#include<crtdbg.h>

int main()
{
    {
        SinglyList nums{};
        nums.Append(10);
        nums.Append(20);
        nums.Append(30);
    }

    _CrtDumpMemoryLeaks();
    return 0;
}

然后,您将在列表被销毁后显示实际泄漏。

【讨论】:

  • 是的,这确实有效;但是我不明白,我在return语句之前使用了_CrtDumpMemoryLeaks()方法,那么添加大括号有什么帮助?
  • 如果没有额外的作用域,你的内存会在 main() 返回之后被释放。因此,即使您将泄漏检查作为最后一条语句,此时列表析构函数还没有运行。它只会在 main() 返回后运行。使用额外的大括号,列表析构函数可以在 _CrtDumpMemoryLeaks 之前运行。
  • @DivijManchanda 解决此问题的另一种方法是实现Clear() 调用的Clear() 方法,然后您也可以在调用_CrtDumpMemoryLeaks() 之前自己调用Clear()。效果一样。
猜你喜欢
  • 1970-01-01
  • 2011-07-17
  • 1970-01-01
  • 1970-01-01
  • 2023-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多