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

C语言读取900万条大数据文件时程序崩溃该如何解决?

C语言大文件读取崩溃问题修复方案

核心崩溃原因

  1. 栈溢出
    你在栈上定义了三个大小为9000000的double数组:double tw[NUM_DATA], ip[NUM_DATA], qp[NUM_DATA]。单个double占8字节,三个数组总大小约为206MB,而操作系统默认栈空间通常仅为1MB~8MB,完全无法容纳这么大的数组,数据量小的时候不会触发栈上限,一旦调到900万就会直接崩溃。
  2. 野指针写入
    你只给signal[num]分配了内存,但是svid[num]没有分配内存就直接执行strcpy(svid[num], h),属于野指针非法写入内存,会直接触发段错误。
  3. 内存分配参数错误
  • 二级指针signal、svid分配内存时多乘了MAX_LENGTH,额外浪费了9倍的指针存储空间,加剧了内存占用压力。
  • 单条字符串分配时错误使用sizeof(char *),应该用sizeof(char),同时需要预留字符串结束符\0的位置。

具体修复步骤

  • 将栈上的三个大数组改为堆上动态分配,避免栈溢出
  • 修正signal、svid的内存分配逻辑,给svid的每一个元素也分配对应的字符串空间
  • 修正循环判断逻辑,废弃错误的feof用法,用fscanf的返回值作为循环终止条件
  • 修正fscanf的格式符错误,跳过不需要的字段避免内存写入错误
  • 增加所有系统调用的错误判断,避免空指针访问
  • 增加边界判断,避免读取数据量超过NUM_DATA导致数组越界

修正后代码

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

#define MAX_LENGTH 10
#define NUM_DATA 9000000

int main(int argc, char **argv){
    if (argc < 2) {
        printf("请传入文件路径参数\n");
        return 1;
    }
    // 二级指针仅分配NUM_DATA个char*的空间即可
    char **signal = malloc(NUM_DATA * sizeof(char *));
    char **svid = malloc(NUM_DATA * sizeof(char *));
    // 大数组改到堆上分配
    double *tw = malloc(NUM_DATA * sizeof(double));
    double *ip = malloc(NUM_DATA * sizeof(double));
    double *qp = malloc(NUM_DATA * sizeof(double));
    // 检查内存分配是否成功
    if (!signal || !svid || !tw || !ip || !qp) {
        printf("内存分配失败\n");
        return 1;
    }

    char GetString[110];
    int num;
    char a[20], b[20], c[20], d[20], e[20], f[20], g[20], h[20], z[20], x[20];

    FILE *fIn = fopen(argv[1], "r");
    if (!fIn) {
        printf("文件打开失败\n");
        return 1;
    }

    // 读取表头
    fgets(GetString, 109, fIn);
    fgets(GetString, 109, fIn);

    // 读取数据
    num = 0;
    // 用fscanf返回值判断是否读取成功,最后一个字段用%*f直接跳过不需要存储
    while (num < NUM_DATA && fscanf(fIn, "%[^','],%[^','],%[^','],%[^','],%[^','],%[^','],%[^','],%[^','],%[^','],%[^','],%*f",
           a, b, c, d, e, f, g, h, z, x) == 10) {
        tw[num] = atof(a);
        ip[num] = atof(z);
        qp[num] = atof(x);
        // 字符串分配正确的大小,预留\0的位置
        signal[num] = malloc(MAX_LENGTH * sizeof(char));
        svid[num] = malloc(MAX_LENGTH * sizeof(char));
        if (!signal[num] || !svid[num]) {
            printf("第%d条数据字符串内存分配失败\n", num);
            break;
        }
        // 用strncpy避免越界
        strncpy(signal[num], f, MAX_LENGTH - 1);
        signal[num][MAX_LENGTH - 1] = '\0';
        strncpy(svid[num], h, MAX_LENGTH - 1);
        svid[num][MAX_LENGTH - 1] = '\0';
        num++;
    }
    fclose(fIn);

    // 这里补充后续业务逻辑,以及使用完后的内存释放逻辑避免内存泄漏
    // ... 业务代码 ...
    // 内存释放
    for (int i = 0; i < num; i++) {
        free(signal[i]);
        free(svid[i]);
    }
    free(signal);
    free(svid);
    free(tw);
    free(ip);
    free(qp);

    return 0;
}

内容的提问来源于stack exchange,提问作者Chun Yen Huang

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 10:15:04