C++ 链表类中的内存泄漏

C++ 链表类中的内存泄漏,c++,C++,如果我在VisualStudio中运行它,它会告诉我存在内存泄漏,但我没有发现析构函数有任何问题。我做错了什么?是因为内存泄漏函数在析构函数之前被调用吗?我不应该在最后调用内存泄漏函数吗 我已经在codereview上发布了这个,他们说它工作得很好,但我当时没有包括析构函数。我现在加了一个,但我不确定它是否真的有效 #define _CRTDBG_MAP_ALLOC #include <stdlib.h> #include <crtdbg.h> #include <

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

我已经在codereview上发布了这个,他们说它工作得很好,但我当时没有包括析构函数。我现在加了一个,但我不确定它是否真的有效

#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 empty\n";
                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 found\n";
                }
                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 found\n";
                return;
            }
            struct node *current = head;
            while ((current->key != key) && (current->next != nullptr)) {
                current = current->next;
            }

            if (current->key == key) {
                cout << "Node found\n";
            }
            else {
                cout << "Node not found\n";
            }
        }

        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();
}
\define\u CRTDBG\u MAP\u ALLOC
#包括
#包括
#包括
使用std::cout;
使用std::cin;
使用std::endl;
结构节点{
int键;
结构节点*下一步;
};
类链表{
私人:
结构节点*头部;
结构节点*尾部;
公众:
链表(){
水头=零PTR;
tail=nullptr;
}
void创建(int键){
结构节点*temp;
temp=新结构节点;
温度->键=键;
temp->next=nullptr;
压头=温度;
尾=头;
}
无效插入(整数键){
如果(键<头->键){
插入_开头(键);
}
如果((head->next==nullptr)| |(key>tail->key)){
插入_端(键);
}
否则{
插入_中间(键);
}
}
无效插入_开头(int键){
if(head->next==nullptr){
尾=头;
}
结构节点*temp;
temp=新结构节点;
温度->键=键;
温度->下一步=头部;
压头=温度;
}
无效插入\u结束(int键){
结构节点*temp;
temp=新结构节点;
温度->键=键;
temp->next=nullptr;
if(head->next==nullptr){
头部->下一步=温度;
尾=温度;
}
否则{
尾部->下一步=温度;
}
尾=温度;
}
无效插入_中间(int键){
结构节点*temp;
temp=新结构节点;
温度->键=键;
结构节点*当前=头部;
结构节点*prev=当前;
同时(当前->按键<临时->按键){
prev=当前值;
当前=当前->下一步;
}
上一个->下一个=温度;
温度->下一步=当前;
} 
void delete_节点(int键){
if(head==nullptr){
cout key==key){
if(head->next==nullptr){
删除(标题);
头=尾=空PTR;
}
结构节点*温度=头部;
头部=头部->下一步;
删除(临时);
}
否则{
结构节点*当前=头部;
结构节点*prev=当前;
while((当前->键!=key)&&(当前->下一步!=nullptr)){
prev=当前值;
当前=当前->下一步;
}
如果((当前->键!=键)&&(当前->下一步==空PTR)){
cout key==key)&&(当前->下一步==nullptr)){
尾部=上一个;
prev->next=nullptr;
删除(当前);
}
否则{
上一个->下一个=当前->下一个;
删除(当前);
}
}
}
无效搜索节点(int键){
如果(头->键==键| |尾->键==键){
cout key!=key)&&(当前->下一步!=nullptr)){
当前=当前->下一步;
}
如果(当前->键==键){
下一步;
删除(上一页);
prev=当前值;
}
删除(上一页);
}
};
内部主(空){
链表;
列表。创建(0);
对于(int i=1;i<20;++i){
清单.插入(i);
}
列表搜索节点(5);
列表。搜索_节点(0);
list.search_节点(-1);
列表。删除_节点(19);
列表。删除_节点(0);
list.print_nodes();
_CrtDumpMemoryLeaks();
}

当您调用
\u CrtDumpMemoryLeaks();
时,您尚未销毁您的
列表
对象

更新

添加一组大括号,以便在执行内存泄漏诊断之前销毁
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();
}
int main(无效){
{
链表;
列表。创建(0);
对于(int i=1;i<20;++i){
清单.插入(i);
}
列表搜索节点(5);
列表。搜索_节点(0);
list.search_节点(-1);
列表。删除_节点(19);
列表。删除_节点(0);
list.print_nodes();
}
_CrtDumpMemoryLeaks();
}

当您调用
\u CrtDumpMemoryLeaks();
时,您尚未销毁您的
列表
对象

更新

添加一组大括号,以便在执行内存泄漏诊断之前销毁
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();
}
int main(无效){
{
链表;
列表。创建(0);
对于(int i=1;i<20;++i){
清单.插入(i);
}
列表搜索节点(5);
列表。搜索_节点(0);
list.search_节点(-1);
列表。删除_节点(19);
列表。删除_节点(0);
list.print_nodes();
}
_CrtDumpMemoryLeaks();
}

使用MSVC尽可能晚地进行泄漏检查的常用方法是启用自动转储功能,代码如下: _CRTSETDBGLAG(_CRTSETDBGLAG(_CRTDBG_报告_标志)| CRTDBG_泄漏检查_DF)


这将在main/WinMain返回且全局对象析构函数运行后执行泄漏检查。如果您曾经看到MFC转储报告,则说明它是如何启用的。

使用MSVC尽可能晚地执行泄漏检查的常用方法是启用自动转储功能,代码如下: _CRTSETDBGLAG(_CRTSETDBGLAG(_CRTDBG_报告_标志)| CRTDBG_泄漏检查_DF)