【问题标题】:How to identify where the memory leak is?如何识别内存泄漏在哪里?
【发布时间】:2025-11-28 03:15:02
【问题描述】:

我正在尝试消除内存泄漏的代码,但不能完全确定泄漏的确切来源。

void insertHead(T value){
        if(!duplicateCheck(value)){
            length++;
            if(head == NULL){
                head = new Node(value);
            }else{
                Node *temp = head;
                head = new Node(value);
                head->next = temp;
            }
        }
  }

void insertTail(T value){
        if(!duplicateCheck(value)){
            // create the node
            if(head == NULL){// insert at the insertHead
                insertHead(value); //head = newNode;
            }else{// Iterators through the linked list until a null is found
                length++;
                Node *fakeIterator = head; // once found sets the null val to newNode
                while(fakeIterator->next != NULL){
                    fakeIterator = fakeIterator->next;
                }
                fakeIterator->next = new Node(value);
            }
        }
  }

void insertAfter(T value, T insertionNode){ // seg faulting because it cant find the object oadd after
        if(!duplicateCheck(value)){
            Node *fakeIterator = head;
            while (fakeIterator != NULL) {
                    if (fakeIterator->value == insertionNode) {
                            Node *newNode = new Node(value);
                            newNode->next = fakeIterator->next;
                            fakeIterator->next = newNode;
                            length++;
                            break;
                    }
                    fakeIterator = fakeIterator->next;
            }
        }
  }

void clear(){
        Node *fakeIterator = head;
        while(fakeIterator!=NULL){
            delete head;
            fakeIterator = fakeIterator->next;
            head = fakeIterator;
        }
        head = NULL;
        length = 0;
  }

Clear 函数在解构器中调用,main 的目的是删除每个节点。我使用了 valgrind,它说所有插入方法都丢失了内存,但我还是不确定在哪里。如果需要,我可以发布 valgrind 输出

【问题讨论】:

  • 提示:在 C++ 中使用 nullptr 而不是 NULL
  • 值得注意的是你的delete 你的fakeIteratorclear() 然后继续使用那个被删除的对象。那是未定义的行为,一个释放后使用的错误。捕获fakeIterator->next你删除之前。
  • 强烈考虑使用std::unique_ptrstd::make_unique() 而不是带有newdelete 的原始指针。
  • 如果head 不是NULLClear() 具有未定义的行为。它所做的第一件事是delete head,它使fakeIterator 无效,因此在赋值fakeIterator = fakeIterator->next 中访问fakeIerator->next 会产生未定义的行为。
  • @tadman @Peter 这会更好吗?我想我需要阅读更多关于 LinkedLists 和内存管理的内容 while(fakeIterator!=NULL){ fakeIterator = fakeIterator->next; delete head; head = fakeIterator; }

标签: c++ memory-leaks valgrind


【解决方案1】:

我假设您已在 Node 构造函数中将 next 字段初始化为 null。

在您的insertTail 函数中,您的循环条件涉及指针访问,如果指针为空,则这是非法的。此外,正如@tadman 提到的,您正在访问已删除的元素。 (注意,访问时,headfakeptr指向同一个元素。如果要删除它们,它们必须指向连续的元素)

通常,使用-g 标志(在 g++ 或 clang++ 的情况下)编译然后运行 ​​valgrind 会输出发生内存泄漏的确切行号。

您也可以同时使用 gdb 和 valgrind。更多信息请参考this link

【讨论】:

  • 您的假设是正确的,在构造函数中将 next 设置为 null。在访问循环中的下一个节点之前,我会检查头部是否为空。由于 fakeptr 设置为 head 不会防止错误吗?