You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

读取简单CSV文件时触发Segmentation fault:11(C语言)

排查并修复CSV读取的段错误问题

你的段错误大概率是由几个常见的内存操作问题导致的,咱们一步步拆解分析:

1. 结构体数组越界访问

你的unused数组大小是MAX_USEABLE,但在readCSV的循环里,i一直递增却没有做边界检查。当CSV的行数超过MAX_USEABLE时,程序会写入到数组之外的内存区域,直接触发段错误。

2. 空指针传入strcpy

如果某一行CSV的列数不足2列(比如只有1列或者空行),getunused会返回NULL。这时候执行strcpy(unused[i].col1, NULL)会因为访问空指针导致段错误。

3. fgets缓冲区大小不匹配

你调用fgets(line, 1024, file),但line的定义是char line[MAX_LINE_LENGTH];。如果MAX_LINE_LENGTH小于1024,会导致缓冲区溢出,破坏栈上的其他数据,进而引发不可预测的错误(包括段错误)。

修复后的代码示例

针对这些问题,咱们修改代码如下:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

// 假设这些宏已经提前定义
#define MAX_ARG_LENGTH 256
#define MAX_USEABLE 100
#define MAX_LINE_LENGTH 1024
#define FIRST_COLUMN 1
#define SECOND_COLUMN 2

struct unused_s{ 
    char col1[MAX_ARG_LENGTH]; 
    char col2[MAX_ARG_LENGTH]; 
}; 

struct unused_s unused[MAX_USEABLE]; 

const char* getunused(char* line, int n) {
    const char* tok;
    // strtok会破坏原字符串,这里传入的是strdup后的副本,无需担心原数据损坏
    for (tok = strtok(line, ";"); tok && *tok; tok = strtok(NULL, ";\n")) {
        if (!--n) {
            // 提前截断过长的列内容,避免后续拷贝溢出
            static char buf[MAX_ARG_LENGTH];
            strncpy(buf, tok, MAX_ARG_LENGTH - 1);
            buf[MAX_ARG_LENGTH - 1] = '\0';
            return buf;
        }
    }
    // 找不到对应列时返回空字符串,避免传入NULL给strcpy
    return "";
}

void readCSV(FILE *file){ 
    int i = 0; 
    char line[MAX_LINE_LENGTH]; 
    // 限制循环次数,彻底避免数组越界
    while (i < MAX_USEABLE && fgets(line, MAX_LINE_LENGTH, file)) { 
        // 跳过空行,减少无效处理
        if (strlen(line) <= 1) continue;
        
        char* tmp = strdup(line); 
        if (!tmp) {
            perror("strdup内存分配失败");
            break;
        }
        
        const char* col1_val = getunused(tmp, FIRST_COLUMN);
        const char* col2_val = getunused(tmp, SECOND_COLUMN);
        
        // 用strncpy替代strcpy,强制限制拷贝长度,防止缓冲区溢出
        strncpy(unused[i].col1, col1_val, MAX_ARG_LENGTH - 1);
        unused[i].col1[MAX_ARG_LENGTH - 1] = '\0';
        
        strncpy(unused[i].col2, col2_val, MAX_ARG_LENGTH - 1);
        unused[i].col2[MAX_ARG_LENGTH - 1] = '\0';
        
        free(tmp); 
        i++; 
    } 
    fclose(file); 
}

额外排查建议

  • 用gdb调试:编译时加上-g参数,运行gdb ./你的程序名,触发段错误后输入bt命令,就能看到精准的出错调用栈。
  • 确认MAX_USEABLE的值是否足够容纳CSV的总行数,避免数组容量不足。
  • 检查CSV文件格式,确认所有行的分隔符都是;,没有异常换行或空列的情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:18:15