You need to enable JavaScript to run this app. C语言使用链表读取存储文本参数时输出异常且触发段错误求助
优惠活动
大模型
产品
解决方案
定价
更多

C语言使用链表读取存储文本参数时输出异常且触发段错误求助

C语言链表功能异常排查与修复

问题根因定位

所有异常现象(重复输出最后一行数据、段错误)均来自代码设计中的四处核心逻辑缺陷:

  • 所有链表节点绑定同一个全局共享内存块
    lists.c 中定义了static修饰的全局变量tempTaskObject,每次调用newData时仅修改这同一块内存的内容;随后调用insert时,直接将该全局变量的地址赋值给新节点的parameters成员。这意味着链表上所有节点的指针最终都指向同一块内存空间,这块空间始终保留最后一次读取的文件行内容,因此遍历输出时会按文件行数重复打印最后一行数据。
  • 首次插入时生成未初始化的野指针节点
    newData函数中status初始值为1,首次调用时会直接malloc一块内存赋值给head,但这块内存没有做任何初始化,next成员为随机野值。紧接着insert函数执行时,会新建一个节点,把新节点的next指向这块未初始化的内存,再把head指针更新为新节点。这会导致链表链路中接入一个内存布局非法的野节点,当遍历到该位置时,尝试访问非法内存的parameters成员就会触发段错误,与测试输出中“打印完与文件行数相等的重复内容后崩溃”的表现完全吻合。
  • 内存释放逻辑非法,破坏堆结构
    main.c中用strdup复制输入行时,返回的是堆内存的起始地址,但后续strsep系列函数会不断修改temp指针的位置,将其移动到分隔符之后。循环末尾调用free(temp)时,传入的已经不是当初malloc返回的合法堆地址,属于非法内存释放,会进一步破坏堆结构,放大程序运行的不稳定性。
  • 头文件缺失保护机制
    function.h未添加标准的头文件重复包含保护逻辑,当多个源文件引用该头文件时,会引发struct node类型的重复定义,导致内存布局错乱、运行时崩溃。

分步修复方案

  • 取消全局共享对象的复用逻辑
    删除lists.c中的全局tempTaskObject、status变量,将head初始值设为NULL。每次调用newData时,为每条数据独立堆分配Parameters结构体内存,将传入的参数值逐一遍历拷贝到独立内存块中,同时为p1字符串单独做堆拷贝,避免节点指向临时/共享内存。
  • 修正内存释放逻辑
    调用strdup时单独记录原始堆内存的起始地址,待strsep操作完成后,用这个原始地址执行free,不得使用被strsep修改过的移位指针做释放。
  • 补全头文件保护逻辑
    为function.h添加和其他头文件一致的#ifndef/#define/#endif保护块,避免重复包含引发的类型重复定义问题。
  • 补充内存回收逻辑
    程序退出前新增专门的链表销毁函数,遍历整个链表依次释放每个节点的parameters内存、节点本身的内存,避免长期运行引发内存泄漏。

关键修复代码片段

lists.c 核心修正部分:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "param.h"
#include "function.h"
#include "lists.h"

static struct node *head = NULL; // 初始头节点为空,无冗余malloc

void newData(char *p1, int p2, int p3){
    // 为每条数据独立分配内存
    Parameters *task = malloc(sizeof(Parameters));
    task->p1 = strdup(p1); // 独立拷贝字符串
    task->p2 = p2;
    task->p3 = p3;
    insert(&head, task); // 传入独立的对象地址
}

void display(){
    traverse(head);
}

main.c 释放逻辑修正部分:

while (fgets(param,100,in) != NULL) {
    char *raw_buf = strdup(param); // 记录strdup返回的原始堆地址
    temp = raw_buf;
    p1 = strsep(&temp,",");
    p2 = atoi(strsep(&temp,","));
    p3 = atoi(strsep(&temp,","));

    newData(p1,p2,p3);
    free(raw_buf); // 用原始地址释放,避免非法free
}

function.h 头文件保护修正:

#ifndef FUNCTION_H
#define FUNCTION_H
#include "param.h"

struct node {
    Parameters * parameters;
    struct node *next;
};

void insert(struct node **head, Parameters * parameters);
void traverse(struct node *head);
#endif

修复后运行效果

程序会通过头插法按逆序输出所有从文件中读取的独立数据行,每一行的参数值独立存储在对应节点的内存块中,链表遍历到最后一个节点的next=NULL时正常退出循环,不会出现重复打印、段错误问题。


内容的提问来源于stack exchange,提问作者Dillion_04

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.31 21:24:01