【问题标题】:C++ linked list memory leakC++链表内存泄漏
【发布时间】:2012-04-14 08:22:48
【问题描述】:

您好,我通过 valgrind 运行了我的程序,这是报告

堆摘要: 在退出时使用:1 个块中的 8 个字节 总堆使用量:1 个分配,0 个释放,8 个字节分配 泄漏摘要: 肯定会丢失:1 个块中的 8 个字节

这是我的程序

int main() {    
NodeData nodedata1(1, 'a');
List list1;
list1.insert(&nodedata1);

   return 0;
}
//---my List class
class List {
public:
   List(); 
   bool insert(NodeData*);                     // insert one Node into list
   bool isEmpty() const; 
private:
   struct Node {              // the node in a linked list
      NodeData* data;         // pointer to actual data, operations in NodeData
      Node* next;
   };
   Node* head;                                 // pointer to first node in list
};
// my bool insert method
bool List::insert(NodeData* rightPtr) {  
   Node* newPtr = new Node;
   newPtr->data = rightPtr;    
   if (isEmpty() || *newPtr->data < *head->data) {
      newPtr->next = head;                           
      head = newPtr;
   }
   else {
      Node* current = head; 
      while (current->next !=NULL && *current->next->data < *newPtr->data) {
           current = current->next;
      }
      newPtr->next = current->next;
      current->next = newPtr;
   }
   return true;
}

【问题讨论】:

  • 列表没有delete这些节点的析构函数
  • 除非这是一个练习或家庭作业,否则你真的应该省去所有这些麻烦,而是使用std::list。
  • 您应该为您的列表创建一个析构函数,以便在列表被销毁时销毁您的所有节点。

标签: c++ memory memory-leaks valgrind


【解决方案1】:

您在insert 方法中动态分配Node 并且永远不会删除它:

Node* newPtr = new Node;

您需要跟踪这些Nodes 并在List 析构函数中删除它们,或者有一些其他安排来处理内存(即将Nodes 的所有权传递给负责删除的东西他们在正确的时刻)。

【讨论】:

  • 不是作业,我只是想学习链表以及析构函数和内存泄漏的工作原理
  • @ThuanTrinh main 中的NodeData 将被自动处理,但List::insert(NodeData* rightPtr) 中的Node* newPtr = new Node 不会。
  • @Thuan Trinh 如果你通过“new”创建一个对象,你总是必须删除它。如果您仅通过声明它来创建项目,它会在堆栈上分配,并且编译器会在它离开范围时注意调用析构函数。这种行为在 RAII 对象中被大量使用(在此处查看:en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization)
  • 您创建的Node 指向您输入的NodeData 指针。但这不是问题。问题是,当您使用 new 创建某些内容时,某处必须删除它。
  • 谢谢大家。我添加了一个析构函数来遍历列表并删除每个节点。
【解决方案2】:

通过声明它创建的对象将在其作用域结束之前被销毁。使用 new 创建的对象不会被销毁,除非您手动删除它。以下示例演示了对象的生命周期。

#include <iostream>
using namespace std;

class Data {
    protected:
        char* name;
    public:
        Data(char* n) {
            name = n;
            cout << name <<  " is created." << endl;
        }

        ~Data() {
            cout << name <<  " is destroyed." << endl;
        }
};

void ScopeDemo() {
    Data obj1("Obj1");
    Data* obj2 = new Data("Obj2");
}

int main()
{
    ScopeDemo();
    return 0;
}

在现代操作系统中,应用程序使用的内存将在应用程序终止时释放。


在您的示例中,当 List 对象被销毁(通过对象析构函数)以及从 List 中删除节点时,您需要手动删除。 p>

List::~List() {
    if (!isEmpty()) {
        Node* toDelete = head;
        while(toDelete != NULL) {
            Node* next = toDelete->next;
            delete toDelete;
            toDelete = next;
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-12-13
    • 2017-09-26
    • 1970-01-01
    • 2022-01-21
    • 1970-01-01
    • 2021-05-19
    • 2021-08-21
    • 2019-12-18
    相关资源
    最近更新 更多