C++ 如何删除链接列表而不发生内存泄漏?

C++ 如何删除链接列表而不发生内存泄漏?,c++,pointers,linked-list,destructor,C++,Pointers,Linked List,Destructor,我正试图制作一个电话簿,我将数据存储在一个链接列表中。然而,当我试图删除它时,我要么得到内存泄漏,要么得到一些丑陋的退出状态以及内存中的一些值。我猜这个退出状态表明在删除我的列表时出现了一些问题,因为程序不会继续下一行 我试过来回摆弄析构函数,但似乎我自己无法解决这个问题 我有三门重要的课。一个用于电话簿,一个用于联系人,一个用于联系人的数据成员。数据类是抽象的,并且有几个派生类。此外,我还有一个链表结构,用于在电话簿中存储联系人,并在联系人中存储数据 链表结构: #include "Data.

我正试图制作一个电话簿,我将数据存储在一个链接列表中。然而,当我试图删除它时,我要么得到内存泄漏,要么得到一些丑陋的退出状态以及内存中的一些值。我猜这个退出状态表明在删除我的列表时出现了一些问题,因为程序不会继续下一行

我试过来回摆弄析构函数,但似乎我自己无法解决这个问题

我有三门重要的课。一个用于电话簿,一个用于联系人,一个用于联系人的数据成员。数据类是抽象的,并且有几个派生类。此外,我还有一个链表结构,用于在电话簿中存储联系人,并在联系人中存储数据

链表结构:

#include "Data.h"
class Contact; //to avoid an "undefined reference" error

struct ListMem{
    ListMem* next=NULL;
    Contact* cont=NULL;
    Data* dat=NULL;
}; //this class can't have a destructor that calls "delete cont",
//because of the order I declared my classes in
电话簿类:

#include "Contact.h"
#include "ListMem.h"

class Phonebook{
    size_t cont_num; //how many contacts are already stored
    ListMem* cont; //pointer to the first member of the linked list
public:
    Phonebook(const char* filename){ //reads the Phonebook from file
        std::ifstream is;
        is.open(filename);
        size_t pb_size;
        string line;
        ListMem* tmp;
        is>>pb_size; getline(is, line);
        cont_num=0;

        for(size_t i=0; i<pb_size; i++){
            getline(is, line);
            if(i==0){
                Contact* tmp_ct=new Contact(line);
                cont=add_cont(tmp_ct);
                tmp=cont;
            }
            else {
                Contact* tmp_ct=new Contact(line);
                tmp->next=add_cont(tmp_ct);
                tmp=tmp->next;
            }
        }
    }

    ListMem* add_cont(Contact* new_ct){ //adds a new contact
        ListMem* tmp=new ListMem;
        tmp->cont=new Contact(new_ct);
        cont_num++;
        return tmp;
    }

    ~Phonebook(){
        ListMem* tmp=cont;
        while(tmp!=NULL){
            ListMem* del=tmp;
            tmp=tmp->next;
            delete del->dat;
            delete del->cont;
            delete del;
        }
    }
};
其中一个派生类,其他派生类看起来基本相同:

#include "Data.h"

class Name: public Data{
    string name;
public:
    Name(string n): name(n){ set_type("1");}
    ~Name(){}
};
当然主要是:

#include "Phonebook.h"

int main(){
    Phonebook* Test=new Phonebook("test.txt");
    delete Test;

    return 0;
}
在“test.txt”文件中,我有我的测试电话簿:

3
1:test_name_1;
1:test_name_2;
1:test_name_3;
所以当我运行这段代码时,我有内存泄漏,我不知道为什么。我让析构函数沿着链表运行并释放动态内存,或者至少我是这么想的

我知道我不会以我应该的方式解除分配联系人,因为我使用了内存泄漏检查工具,并且一个模式会重复与我拥有的联系人相同的时间

我使用了.cpp文件,但我在这里集成了相关部分以节省一些空间。此外,除了我的项目系统之外,我没有在这里添加其他内容

我强烈怀疑问题出在析构函数上,~Phonebook、~Contact或两者都有。我把其他部分放在这里是因为我被告知发布一个任何人都可以轻松复制的版本。我觉得一定有一个愚蠢的错误和一个简单的解决方案,但我不知道是什么


你们能帮我一点忙吗?

电话簿构造函数解析文件,使用新运算符创建联系人对象,并将其传递给add_cont。成员函数add_cont使用新运算符再次创建作为参数传递的联系人对象的副本,但从不删除源。 从我的观点来看,在add_cont中,“new_ct”可以被分配到“tmp->cont”


顺便说一句,更好的方法是使用可用的容器类,如std::list、std::vector等,并避免使用原始指针。

当我尝试删除它时,我要么得到内存泄漏,要么得到内存中带有某个值的丑陋退出状态。你为什么不把那些贴上去?。无论如何,在电话簿中:添加行ListMem*tmp=newlistmem;tmp->cont=新触点新触点;看起来可疑。这是如何编译的呢?A将更容易诊断。另外,创建一个最小但完整的示例的过程可能会告诉您错误所在。完整地说,示例不应该依赖于数据文件。尝试用硬编码的伪数据创建一个示例,而不是从文件中读取。@Quimby抱歉,我认为它们在任何方面都没有用处。我使用了学校提供的内存跟踪程序,所以我不确定输出是否是标准的。下次我一定会把它们包括进去。是的,这就是问题所在,谢谢。但你为什么要问这是怎么做到的?编译器应该注意到这样的事情吗?@Heves遗憾的是,它通常不会/不能,但我的观点是newcontactnew\u ct调用构造函数Contact::ContactContact*ptr,而没有。如果它是Contact*new\u ct,那么将调用一个拷贝ctor,它是存在的。那只是打字错误吗?如果没有,编译器应该抱怨。除此之外,发布错误消息不会造成伤害,而且通常是有帮助的。例如,valgrind通常至少可以指向创建泄漏对象的分配代码。但很高兴看到问题解决了:。新的ListMem之间也有区别;和新列表;谢谢你的回答,你是对的。我为学校做这个项目,他们告诉我们不要使用STL容器,这就是为什么我要玩链表。我们只学习基本的C++,它们实际上没有教给我们最新的特性,或者C++ 11或任何关于原始指针的东西。这在现实生活中无疑是有用的,但学校就是这样。再次感谢你。
#include "Phonebook.h"

int main(){
    Phonebook* Test=new Phonebook("test.txt");
    delete Test;

    return 0;
}
3
1:test_name_1;
1:test_name_2;
1:test_name_3;