如何在没有内存泄漏的情况下删除链表?
How can I delete a linked list without memory leak?
我正在尝试制作一本 phone 书,我将我的数据存储在一个链表中。但是,当我尝试删除它时,我要么得到内存泄漏,要么得到一些丑陋的退出状态,其中有一些内存值。我想这个退出状态表示在删除我的列表期间出现了一些问题,因为程序不会继续到下一行。
我试过来回摆弄析构函数,但似乎我无法独自解决这个问题。
我有三个重要的 classes。一个用于电话簿,一个用于联系人,一个用于联系人的数据成员。数据 class 是抽象的,并且有一些派生的 classes。我还有一个链接列表结构,用于在电话簿中存储联系人,并在联系人中存储数据。
链表结构:
#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
电话簿class:
#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;
}
}
};
联系人class:
#include "Name.h"
#include "ListMem.h"
class Contact{
size_t data_num; //number of data stored
ListMem* data; //pointer to the first data member
public:
Contact(string line){ //converts a "line" into a Contact
ListMem* tmp;
int dat_count=std::count(line.begin(), line.end(), ':');
data_num=dat_count;
string dat, tmp_dat, tmp_type;
int pos_1=0, pos_2=line.find(';');
for(int i=0;i<dat_count;i++){
dat=line.substr(pos_1, pos_2-pos_1);
tmp_type=dat.at(0);
tmp_dat=dat.substr(2, dat.size()-2);
pos_1+=dat.size()+1;
pos_2=line.find(';', pos_1);
if(i==0){
data=add_data(tmp_type, tmp_dat);
tmp=data;
}
else {
tmp->next=add_data(tmp_type, tmp_dat);
tmp=tmp->next;
}
}
}
ListMem* add_data(string type, string data){ //adds a new data member
ListMem* tmp=new ListMem;
if(type=="1") tmp->dat=new Name(data);
//I have more, but it's irrelevant.
data_num++;
return tmp;
}
~Contact(){
ListMem* tmp=data;
while(tmp!=NULL){
ListMem* del=tmp;
tmp=tmp->next;
delete del->dat;
delete del->cont;
delete del;
}
}
};
数据class:
class Data{
string type;
public:
Data(){}
void set_type(string t) {type=t;}
virtual ~Data(){}
};
其中一个派生出来的classes,其他的看起来基本一样:
#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'文件中,我有我的测试phone书:
3
1:test_name_1;
1:test_name_2;
1:test_name_3;
所以当我运行这段代码时,我有内存泄漏,我不知道为什么。我沿着链表创建了析构函数 运行 并释放了动态内存,或者至少我是这么想的。
我知道我没有按照我应该的方式解除分配联系人,因为我使用了内存泄漏检查工具,并且模式重复了我拥有的联系人的相同时间。
我用的是.cpp文件,这里整合了相关部分,节省一些space。此外,除了我的项目系统之外,我没有将其他内容放在这里。
我强烈怀疑问题出在析构函数上,~Phonebook()、~Contact() 或两者都有。我把其他部分放在这里是因为有人告诉我 post 一个任何人都可以毫不费力地复制的版本。我觉得一定有一个愚蠢的错误和一个简单的解决方案,但我不知道是什么。
你们能帮帮我吗?
Phonebook 构造函数解析文件,使用 new 运算符创建 Contact 对象并将其传递给 add_cont()。成员函数 add_cont() 使用 new 运算符再次创建作为参数传递的 Contact 对象的副本,但从不删除原点。
从我的角度来看 add_cont() 'new_ct' 可以分配给 'tmp->cont'.
顺便说一句,更好的方法是使用可用容器 类,如 std::list、std::vector 等,并避免使用原始指针。
我正在尝试制作一本 phone 书,我将我的数据存储在一个链表中。但是,当我尝试删除它时,我要么得到内存泄漏,要么得到一些丑陋的退出状态,其中有一些内存值。我想这个退出状态表示在删除我的列表期间出现了一些问题,因为程序不会继续到下一行。
我试过来回摆弄析构函数,但似乎我无法独自解决这个问题。
我有三个重要的 classes。一个用于电话簿,一个用于联系人,一个用于联系人的数据成员。数据 class 是抽象的,并且有一些派生的 classes。我还有一个链接列表结构,用于在电话簿中存储联系人,并在联系人中存储数据。
链表结构:
#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
电话簿class:
#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;
}
}
};
联系人class:
#include "Name.h"
#include "ListMem.h"
class Contact{
size_t data_num; //number of data stored
ListMem* data; //pointer to the first data member
public:
Contact(string line){ //converts a "line" into a Contact
ListMem* tmp;
int dat_count=std::count(line.begin(), line.end(), ':');
data_num=dat_count;
string dat, tmp_dat, tmp_type;
int pos_1=0, pos_2=line.find(';');
for(int i=0;i<dat_count;i++){
dat=line.substr(pos_1, pos_2-pos_1);
tmp_type=dat.at(0);
tmp_dat=dat.substr(2, dat.size()-2);
pos_1+=dat.size()+1;
pos_2=line.find(';', pos_1);
if(i==0){
data=add_data(tmp_type, tmp_dat);
tmp=data;
}
else {
tmp->next=add_data(tmp_type, tmp_dat);
tmp=tmp->next;
}
}
}
ListMem* add_data(string type, string data){ //adds a new data member
ListMem* tmp=new ListMem;
if(type=="1") tmp->dat=new Name(data);
//I have more, but it's irrelevant.
data_num++;
return tmp;
}
~Contact(){
ListMem* tmp=data;
while(tmp!=NULL){
ListMem* del=tmp;
tmp=tmp->next;
delete del->dat;
delete del->cont;
delete del;
}
}
};
数据class:
class Data{
string type;
public:
Data(){}
void set_type(string t) {type=t;}
virtual ~Data(){}
};
其中一个派生出来的classes,其他的看起来基本一样:
#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'文件中,我有我的测试phone书:
3
1:test_name_1;
1:test_name_2;
1:test_name_3;
所以当我运行这段代码时,我有内存泄漏,我不知道为什么。我沿着链表创建了析构函数 运行 并释放了动态内存,或者至少我是这么想的。
我知道我没有按照我应该的方式解除分配联系人,因为我使用了内存泄漏检查工具,并且模式重复了我拥有的联系人的相同时间。
我用的是.cpp文件,这里整合了相关部分,节省一些space。此外,除了我的项目系统之外,我没有将其他内容放在这里。
我强烈怀疑问题出在析构函数上,~Phonebook()、~Contact() 或两者都有。我把其他部分放在这里是因为有人告诉我 post 一个任何人都可以毫不费力地复制的版本。我觉得一定有一个愚蠢的错误和一个简单的解决方案,但我不知道是什么。
你们能帮帮我吗?
Phonebook 构造函数解析文件,使用 new 运算符创建 Contact 对象并将其传递给 add_cont()。成员函数 add_cont() 使用 new 运算符再次创建作为参数传递的 Contact 对象的副本,但从不删除原点。 从我的角度来看 add_cont() 'new_ct' 可以分配给 'tmp->cont'.
顺便说一句,更好的方法是使用可用容器 类,如 std::list、std::vector 等,并避免使用原始指针。