
C语言 链表的内存分配和FREE出现问题了!(内附问题详细说明)
有点长,请各位大大耐心看下去~然后解答~谢谢(∩_∩)我创建了一个单向链表,代码如下:typedefstructnode{unsignedchar*name;intdat...
有点长,请各位大大耐心看下去~然后解答~谢谢(∩_∩)
我创建了一个单向链表,代码如下:
typedef struct node
{
unsigned char * name;
int data;
struct node * next;
} HEAD ;
这个链表用来储存一个dir下的所有文件的名字.
接着是跟问题相关的几个函数:
函数1:在链表最后创建新节点
void addEnd (char num, unsigned char *name,HEAD **list)
{
HEAD *toAdd, *current;
toAdd = (HEAD *)calloc(sizeof(HEAD),1);
toAdd->name = (char *)calloc( strlen(name), sizeof(unsigned char));
toAdd->data = num;
strcpy(toAdd->name, name);
current=*list;
if(current == NULL ){
*list=toAdd;
(*list)->next=NULL;
}else{
while(current->next != NULL) current=current->next;
toAdd->next=NULL;
current->next=toAdd;
}
}
函数2:算链表内节点总数
unsigned char list_length(HEAD **list)
{
HEAD *cur_ptr;
unsigned char count=0;
cur_ptr=*list;
while(cur_ptr != NULL)
{
cur_ptr=cur_ptr->next;
count++;
}
return(count);
}
函数3:删除一个节点(节点位置为参数)
int delnodeLoc(int loc,HEAD **list)
{
HEAD *prev_ptr, *cur_ptr;
int i;
cur_ptr=*list;
if(loc > (list_length(list)) || loc <= 0)
{
printf("\nDeletion impossible\n ");
}
else
{
if (loc == 1)
{
*list=cur_ptr->next;
free(cur_ptr->name);
free(cur_ptr);
cur_ptr= NULL;
return 0;
}
else
{
for(i=1;i<loc;i++)
{
prev_ptr=cur_ptr;
cur_ptr=cur_ptr->next;
}
prev_ptr->next=cur_ptr->next;
free(cur_ptr->name);
free(cur_ptr);
cur_ptr= NULL;
}
}
return 0;
}
函数4:清空链表(从最后一个节点开始删)
unsigned char clear_list(HEAD **list)
{
int i,nf;
nf = list_length(list);
for(i=nf;i>=1;i--){
delnodeLoc(i,list);
}
return 0;
}
//===========
我的主函数:
EXTERN HEAD * file_list
int main(){
...省略变量声明
clear_list(&file_list); // 清空链表
while ((entry = readdir(dir))) { // 读取一个文件的信息
files++;
addEnd(files,entry->d_name,&file_list); // entry->d_name为该文件的名字指针
}
......上面这5排程序重复运行N次
}
好了,问题出现了,上面这段主函数中,前面5次重复运行那一小段程序,都能成功将所有文件信息填入到file_list这个链表中,从第6次开始(有时第7次),当读完第4个文件后,读取第5个文件时addEnd这个函数中给toAdd分配内存的那一句toAdd = (HEAD *)calloc(sizeof(HEAD),1); 返回总是NULL。已知前几次是能够成功运行的,所以可以预见的错误可能是清空链表时出现内存泄露。
反复检查以后,我确实在每删除一个节点后,都FREE掉了节点中被分配了内存的指针,然后FREE掉该节点,然后将指向该节点的指针置0了。
我实在不知道为什么在5次清空再填入链表后,再进行这一行为会出现分配内存失败的原因。
希望各位大大耐心看完以上内容,真心感激不尽。。 展开
我创建了一个单向链表,代码如下:
typedef struct node
{
unsigned char * name;
int data;
struct node * next;
} HEAD ;
这个链表用来储存一个dir下的所有文件的名字.
接着是跟问题相关的几个函数:
函数1:在链表最后创建新节点
void addEnd (char num, unsigned char *name,HEAD **list)
{
HEAD *toAdd, *current;
toAdd = (HEAD *)calloc(sizeof(HEAD),1);
toAdd->name = (char *)calloc( strlen(name), sizeof(unsigned char));
toAdd->data = num;
strcpy(toAdd->name, name);
current=*list;
if(current == NULL ){
*list=toAdd;
(*list)->next=NULL;
}else{
while(current->next != NULL) current=current->next;
toAdd->next=NULL;
current->next=toAdd;
}
}
函数2:算链表内节点总数
unsigned char list_length(HEAD **list)
{
HEAD *cur_ptr;
unsigned char count=0;
cur_ptr=*list;
while(cur_ptr != NULL)
{
cur_ptr=cur_ptr->next;
count++;
}
return(count);
}
函数3:删除一个节点(节点位置为参数)
int delnodeLoc(int loc,HEAD **list)
{
HEAD *prev_ptr, *cur_ptr;
int i;
cur_ptr=*list;
if(loc > (list_length(list)) || loc <= 0)
{
printf("\nDeletion impossible\n ");
}
else
{
if (loc == 1)
{
*list=cur_ptr->next;
free(cur_ptr->name);
free(cur_ptr);
cur_ptr= NULL;
return 0;
}
else
{
for(i=1;i<loc;i++)
{
prev_ptr=cur_ptr;
cur_ptr=cur_ptr->next;
}
prev_ptr->next=cur_ptr->next;
free(cur_ptr->name);
free(cur_ptr);
cur_ptr= NULL;
}
}
return 0;
}
函数4:清空链表(从最后一个节点开始删)
unsigned char clear_list(HEAD **list)
{
int i,nf;
nf = list_length(list);
for(i=nf;i>=1;i--){
delnodeLoc(i,list);
}
return 0;
}
//===========
我的主函数:
EXTERN HEAD * file_list
int main(){
...省略变量声明
clear_list(&file_list); // 清空链表
while ((entry = readdir(dir))) { // 读取一个文件的信息
files++;
addEnd(files,entry->d_name,&file_list); // entry->d_name为该文件的名字指针
}
......上面这5排程序重复运行N次
}
好了,问题出现了,上面这段主函数中,前面5次重复运行那一小段程序,都能成功将所有文件信息填入到file_list这个链表中,从第6次开始(有时第7次),当读完第4个文件后,读取第5个文件时addEnd这个函数中给toAdd分配内存的那一句toAdd = (HEAD *)calloc(sizeof(HEAD),1); 返回总是NULL。已知前几次是能够成功运行的,所以可以预见的错误可能是清空链表时出现内存泄露。
反复检查以后,我确实在每删除一个节点后,都FREE掉了节点中被分配了内存的指针,然后FREE掉该节点,然后将指向该节点的指针置0了。
我实在不知道为什么在5次清空再填入链表后,再进行这一行为会出现分配内存失败的原因。
希望各位大大耐心看完以上内容,真心感激不尽。。 展开
若以下回答无法解决问题,邀请你更新回答
展开全部
1.addEnd():
toAdd->name = (char *)calloc( strlen(name), sizeof(unsigned char));
c的标准字符串为null结尾,故该改为:
toAdd->name = (char *)calloc( strlen(name)+1, sizeof(unsigned char));
还有你的链表每个节点中的DATA都是有效值,而一般都是以next的有效性(是否为null值)判断data的有效性,即一个数据上的“空”链表总有以个节点。你的链表不容易初始化、重用和销毁。
2.addEnd():
strcpy(toAdd->name, name);
改用strncpy(),strncpy(toAdd->name,name,strlen(name)+1),strcpy()一旦越界操作,势必出现不可预料的错误。比如free()时。
ps:
语句:files++; addEnd(files,entry->d_name,&file_list);
真心不知道存储files有什么意思,你把i节点号存储在链表中,遍历时可以作为参数调用某些系统函数呀。。。。一个普通序列号,遍历链表就可以得到了。。去我的空间看看有很多链表的操作,链表不是你这么用的。
toAdd->name = (char *)calloc( strlen(name), sizeof(unsigned char));
c的标准字符串为null结尾,故该改为:
toAdd->name = (char *)calloc( strlen(name)+1, sizeof(unsigned char));
还有你的链表每个节点中的DATA都是有效值,而一般都是以next的有效性(是否为null值)判断data的有效性,即一个数据上的“空”链表总有以个节点。你的链表不容易初始化、重用和销毁。
2.addEnd():
strcpy(toAdd->name, name);
改用strncpy(),strncpy(toAdd->name,name,strlen(name)+1),strcpy()一旦越界操作,势必出现不可预料的错误。比如free()时。
ps:
语句:files++; addEnd(files,entry->d_name,&file_list);
真心不知道存储files有什么意思,你把i节点号存储在链表中,遍历时可以作为参数调用某些系统函数呀。。。。一个普通序列号,遍历链表就可以得到了。。去我的空间看看有很多链表的操作,链表不是你这么用的。
本回答被提问者和网友采纳
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
我朋友聪少是这方面大牛,LZ如果需要,我可以把他的QQ发给你。
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询