链表类中的内存泄漏

Memory leak in linked list class

本文关键字:内存 泄漏 链表      更新时间:2023-10-16

如果我在Visual Studio中运行它,它会告诉我存在内存泄漏,但我没有看到我的析构函数有什么问题。我做错了什么?是因为在析构函数之前调用内存泄漏函数吗?我不应该在最后调用内存泄漏函数吗?

我已经在代码审查上发布了这个,他们说它工作正常,但当时我没有包含析构函数。我现在添加了一个,但我不确定它是否真的有效。

#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#include <iostream>
using  std::cout;
using  std::cin;
using  std::endl;
struct node {
    int key;
    struct node *next;
};
class linked_list {
    private:
        struct node *head;
        struct node *tail;
    public:
        linked_list() {
            head = nullptr;
            tail = nullptr;
        }
        void create(int key) {
            struct node *temp;
            temp = new struct node;
            temp->key = key;
            temp->next = nullptr;
            head = temp;
            tail = head;
        }

        void insert(int key) {
            if (key < head->key) {
                insert_beginning(key);
            }
            else if ((head->next == nullptr) || (key > tail->key)) {
                insert_end(key);
            }
            else {
                insert_middle(key);
            }
        }
        void insert_beginning(int key) {
            if (head->next == nullptr) {
                tail = head;
            }
            struct node *temp;
            temp = new struct node;
            temp->key = key;
            temp->next = head;
            head = temp;
        }
        void insert_end(int key) {
            struct node *temp;
            temp = new struct node;
            temp->key = key;
            temp->next = nullptr;
            if (head->next == nullptr) {
                head->next = temp;
                tail = temp;
            }
            else {
                tail->next = temp;
            }
            tail = temp;
        }

        void insert_middle(int key) {
            struct node *temp;
            temp = new struct node;
            temp->key = key;
            struct node *current = head;
            struct node *prev = current;
            while (current->key < temp->key) {
                prev = current;
                current = current->next;
            }
            prev->next = temp;
            temp->next = current;
        } 
        void delete_node(int key) {
            if (head == nullptr) {
                cout << "List is emptyn";
                return;
            }
            if (head->key == key) {
                if (head->next == nullptr) {
                    delete(head);
                    head = tail = nullptr;
                }
                struct node *temp = head;
                head = head->next;
                delete(temp);
            }
            else {
                struct node *current = head;
                struct node *prev = current;
                while ((current->key != key) && (current->next != nullptr)) {
                    prev = current;
                    current = current->next;
                }
                if ((current->key != key) && (current->next == nullptr)) {
                    cout << "Key not foundn";
                }
                else if ((current->key == key) && (current->next == nullptr)) {
                    tail = prev;
                    prev->next = nullptr;
                    delete(current);
                }
                else {
                    prev->next = current->next;
                    delete(current);
                }
            }
        }
        void search_node(int key) {
            if (head->key == key || tail->key == key) {
                cout << "Node foundn";
                return;
            }
            struct node *current = head;
            while ((current->key != key) && (current->next != nullptr)) {
                current = current->next;
            }
            if (current->key == key) {
                cout << "Node foundn";
            }
            else {
                cout << "Node not foundn";
            }
        }
        void print_nodes(void) {
            struct node *current = head;
            while (current != nullptr) {
                cout << current->key << 'n';
                current = current->next;
            }
        }
        ~linked_list() {
            struct node *current = head;
            struct node *prev = current;
            while (current->next != nullptr) {
                current = current->next;
                delete(prev);
                prev = current;
            }
            delete(prev);
        }
};

int main(void) {
    linked_list list;
    list.create(0);
    for (int i = 1; i < 20; ++i) {
        list.insert(i);
    }
    list.search_node(5);
    list.search_node(0);
    list.search_node(-1);
    list.delete_node(19);
    list.delete_node(0);
    list.print_nodes();
    _CrtDumpMemoryLeaks();
}

当你调用_CrtDumpMemoryLeaks();时,你还没有破坏你的list对象。

更新

添加一组大括号,以便在执行内存泄漏诊断之前破坏list

int main(void) {
  {
    linked_list list;
    list.create(0);
    for (int i = 1; i < 20; ++i) {
        list.insert(i);
    }
    list.search_node(5);
    list.search_node(0);
    list.search_node(-1);
    list.delete_node(19);
    list.delete_node(0);
    list.print_nodes();
  }
  _CrtDumpMemoryLeaks();
}

使用 MSVC 尽可能晚地执行泄漏检查的常用方法是使用以下代码启用自动转储功能: _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG(|_CRTDBG_LEAK_CHECK_DF(;

这将在 main/WinMain 返回并且全局对象析构函数运行后执行泄漏检查。如果您曾经看过 MFC 转储报告,那就是它的启用方式。