以下是 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;
}

问题分析及优化方案

  1. 内存泄漏

    • initList()newNode() 中使用 calloc() 分配内存后,没有在适当的时候使用 free() 释放内存,导致内存泄漏。
    • 解决方案:在 main() 函数中,使用 list_for_each_entry_safe 遍历链表,释放每个节点的内存,最后释放链表头节点。
  2. 字符串指针问题

    • newNode() 中,将传入的字符串指针 name 直接赋值给新节点的 name 成员,这样做可能会导致问题。因为在后续的操作中,如果修改了原始字符串的内容,那么所有指向该字符串的指针都会受到影响。
    • 解决方案:为每个节点的 name 成员分配独立的内存空间,并将字符串内容复制到该空间中,使用 malloc()strcpy() 完成。
  3. 文件打开失败处理不准确

    • 在打开文件后,应该使用 if (fp == NULL) 来判断文件是否成功打开,而不是使用 ferror(fp)。因为 ferror(fp) 只能判断上一次文件操作是否发生了错误,无法准确判断文件是否成功打开。
    • 解决方案:在打开文件后,使用 if (fp == NULL) 来判断文件是否成功打开。
  4. 文件读取错误处理不完善

    • 在从文件中读取数据后,没有进行错误处理。应该检查读取操作是否成功,并根据需要进行错误处理。
    • 解决方案:使用 fscanf() 返回值判断读取操作是否成功,如果失败,则输出错误信息并退出程序。
  5. 文件读取循环条件不准确

    • 在读取文件内容时,循环条件是 while(1),这会导致无限循环。应该根据实际情况设置循环条件,如读取到文件末尾时退出循环。
    • 解决方案:使用 feof(fp) 判断是否读取到文件末尾,如果读取到文件末尾,则退出循环。
  6. 文件关闭问题

    • 在文件读取完成后,应该使用 fclose(fp) 关闭文件,以释放相关资源。
    • 解决方案:在 main() 函数中,使用 fclose(fp) 关闭文件。
  7. 函数命名不规范

    • 函数名应该使用小写字母开头,采用驼峰命名法,以提高代码的可读性和一致性。例如,init_list() 应该改为 initList()new_node() 应该改为 newNode()
    • 解决方案:将函数名改为驼峰命名法。
  8. 缺少头文件

    • 代码中使用了 kernel_list.h,但没有提供该头文件的内容。应该包含正确的头文件,以便编译器正确解析相关函数和数据结构的定义。
    • 解决方案:提供 kernel_list.h 头文件内容,或确保该头文件已经包含在项目中。

总结

以上代码优化方案可以解决代码中存在的内存泄漏、字符串指针、文件操作错误处理等问题,并提高代码的可读性和安全性。

C 语言内核链表操作代码优化及问题分析 - 内存泄漏,字符串指针,文件操作错误处理

原文地址: https://www.cveoy.top/t/topic/qmUi 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录