C语言内核链表实现:优化与分析
以下是经过优化后的代码,并修复了代码中的问题:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <string.h>
#include "kernel_list.h"
typedef struct node
{
char *name;
int time;
struct list_head list;
}listnode,*linklist;
linklist init_list()
{
linklist head = calloc(1,sizeof(listnode));
if(head==NULL)
{
perror("内存分配失败!");
exit(1);
}
INIT_LIST_HEAD(&head->list);
return head;
}
linklist new_node(char *name,int time)
{
linklist new = calloc(1,sizeof(listnode));
if(new==NULL)
{
perror("内存分配失败!");
exit(1);
}
new->name=name;
new->time=time;
INIT_LIST_HEAD(&new->list);
return new;
}
void show(linklist head)
{
linklist pos;
list_for_each_entry(pos,&head->list.next,list)
{
printf("%s %d\n",pos->name,pos->time);
}
}
int main()
{
//内核链表初始化
linklist head=init_list();
//打开,读取'record.txt'文件,写入内核链表中
FILE *fp=fopen("record.txt","r");
if(ferror(fp))
{
perror("文件打开失败!");
exit(0);
}
int i =1;
while(1)
{
char name_buf[20];
int time_buf;
fscanf(fp,"%s %d",name_buf,&time_buf);
// char flag;
// while(flag!='\n') flag=fgetc(fp);
linklist new=new_node(name_buf,time_buf);
list_add_tail(&(new->list),&(head->list));
if(feof(fp)) break;
}
show(head);
fclose(fp); // 关闭文件指针
// 释放内存
linklist pos, n;
list_for_each_entry_safe(pos, n, &head->list, list) {
free(pos->name);
list_del(&pos->list);
free(pos);
}
free(head);
return 0;
}
代码优化和问题分析
-
内存分配错误: 在函数
init_list()和new_node()中,使用calloc()动态分配内存后,需要进行内存分配成功的判断。如果分配失败,则返回 NULL 并打印错误信息,避免程序崩溃。 -
链表遍历错误: 在函数
show()中,使用list_for_each_entry()遍历链表时,应该从head->list.next开始遍历,而不是从head->list开始遍历。 -
资源泄露: 在函数
main()中,没有关闭打开的文件指针fp,可能导致文件资源泄露。在程序结束前,使用fclose(fp)关闭文件指针。 -
内存泄露: 在函数
main()中,没有释放动态分配的内存,可能导致内存泄露。使用list_for_each_entry_safe遍历链表并释放每个节点的内存,最后释放链表的头节点。
其他优化建议
- 使用
const修饰name_buf数组,防止其在函数内部被意外修改。 - 可以使用
fgets()读取文件内容,避免fscanf()潜在的缓冲区溢出风险。 - 考虑使用
struct结构体来封装节点数据,提高代码的可读性和可维护性。
通过以上优化和问题分析,可以提高代码的可靠性和安全性,避免内存泄漏和资源泄露问题。同时,代码结构也更加合理,可读性更强。
原文地址: https://www.cveoy.top/t/topic/qmT8 著作权归作者所有。请勿转载和采集!