C 语言内核链表操作代码优化及问题分析 - 内存泄漏,字符串指针,文件操作错误处理
以下是 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 initList()
{
linklist head = calloc(1,sizeof(listnode));
if(head!=NULL)
{
INIT_LIST_HEAD(&head->list);
}
return head;
}
linklist newNode(char *name,int time)
{
linklist new = calloc(1,sizeof(listnode));
if(new!=NULL)
{
new->name = malloc(strlen(name) + 1);
if (new->name == NULL) {
free(new);
return NULL;
}
strcpy(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,list)
{
printf("%s %d\n",pos->name,pos->time);
}
}
int main()
{
//内核链表初始化
linklist head=initList();
//打开,读取“record.txt”文件,写入内核链表中
FILE *fp=fopen("record.txt","r");
if (fp == NULL)
{
perror("文件打开失败!");
exit(1);
}
int i =1;
while(1)
{
char name_buf[20];
int time_buf;
if (fscanf(fp, "%s %d", name_buf, &time_buf) != 2) {
if (feof(fp)) {
break;
} else {
perror("读取文件失败!");
exit(1);
}
}
linklist new=newNode(name_buf,time_buf);
if (new == NULL) {
perror("创建节点失败!");
exit(1);
}
list_add_tail(&(new->list),&(head->list));
}
show(head);
// 释放内存
linklist pos, next;
list_for_each_entry_safe(pos, next, &head->list, list) {
free(pos->name);
list_del(&pos->list);
free(pos);
}
free(head);
fclose(fp);
return 0;
}
问题分析及优化方案
-
内存泄漏
- 在
initList()和newNode()中使用calloc()分配内存后,没有在适当的时候使用free()释放内存,导致内存泄漏。 - 解决方案:在
main()函数中,使用list_for_each_entry_safe遍历链表,释放每个节点的内存,最后释放链表头节点。
- 在
-
字符串指针问题
- 在
newNode()中,将传入的字符串指针name直接赋值给新节点的name成员,这样做可能会导致问题。因为在后续的操作中,如果修改了原始字符串的内容,那么所有指向该字符串的指针都会受到影响。 - 解决方案:为每个节点的
name成员分配独立的内存空间,并将字符串内容复制到该空间中,使用malloc()和strcpy()完成。
- 在
-
文件打开失败处理不准确
- 在打开文件后,应该使用
if (fp == NULL)来判断文件是否成功打开,而不是使用ferror(fp)。因为ferror(fp)只能判断上一次文件操作是否发生了错误,无法准确判断文件是否成功打开。 - 解决方案:在打开文件后,使用
if (fp == NULL)来判断文件是否成功打开。
- 在打开文件后,应该使用
-
文件读取错误处理不完善
- 在从文件中读取数据后,没有进行错误处理。应该检查读取操作是否成功,并根据需要进行错误处理。
- 解决方案:使用
fscanf()返回值判断读取操作是否成功,如果失败,则输出错误信息并退出程序。
-
文件读取循环条件不准确
- 在读取文件内容时,循环条件是
while(1),这会导致无限循环。应该根据实际情况设置循环条件,如读取到文件末尾时退出循环。 - 解决方案:使用
feof(fp)判断是否读取到文件末尾,如果读取到文件末尾,则退出循环。
- 在读取文件内容时,循环条件是
-
文件关闭问题
- 在文件读取完成后,应该使用
fclose(fp)关闭文件,以释放相关资源。 - 解决方案:在
main()函数中,使用fclose(fp)关闭文件。
- 在文件读取完成后,应该使用
-
函数命名不规范
- 函数名应该使用小写字母开头,采用驼峰命名法,以提高代码的可读性和一致性。例如,
init_list()应该改为initList(),new_node()应该改为newNode()。 - 解决方案:将函数名改为驼峰命名法。
- 函数名应该使用小写字母开头,采用驼峰命名法,以提高代码的可读性和一致性。例如,
-
缺少头文件
- 代码中使用了
kernel_list.h,但没有提供该头文件的内容。应该包含正确的头文件,以便编译器正确解析相关函数和数据结构的定义。 - 解决方案:提供
kernel_list.h头文件内容,或确保该头文件已经包含在项目中。
- 代码中使用了
总结
以上代码优化方案可以解决代码中存在的内存泄漏、字符串指针、文件操作错误处理等问题,并提高代码的可读性和安全性。
原文地址: https://www.cveoy.top/t/topic/qmUi 著作权归作者所有。请勿转载和采集!