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

C语言实现文件反转时用fread读取大MP4文件触发段错误,如何解决?

解决大文件读取触发Segmentation Fault的问题

问题原因

你代码里的char data[fsize];是在栈内存上分配的数组,而栈的默认空间通常只有几MB(比如Linux默认8MB,Windows多为1-8MB),34MB的数组直接占满栈空间,导致栈溢出,触发Segmentation Fault。

修复方案

方案1:使用堆内存动态分配

用malloc在堆上分配内存,堆的空间远大于栈,能容纳大文件数据,记得用完后用free释放内存,同时补充文件大小动态获取、文件打开检查和反转逻辑:

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

int main()
{
    FILE *fh = fopen("vid.mp4", "rb");
    FILE *fh1 = fopen("vid1.mp4", "wb"); // 保持原后缀,避免格式识别混乱

    // 检查文件是否打开成功
    if (!fh || !fh1) {
        perror("文件打开失败");
        return 1;
    }

    // 动态获取文件大小
    fseek(fh, 0, SEEK_END);
    long fsize = ftell(fh);
    fseek(fh, 0, SEEK_SET);

    // 在堆上分配内存
    char *data = (char*)malloc(fsize);
    if (!data) {
        perror("内存分配失败");
        fclose(fh);
        fclose(fh1);
        return 1;
    }

    // 读取文件内容
    size_t read_bytes = fread(data, 1, fsize, fh);
    if (read_bytes != fsize) {
        perror("文件读取不完整");
        free(data);
        fclose(fh);
        fclose(fh1);
        return 1;
    }

    // 反转数据(实现文件不可读的核心逻辑)
    for (long i = 0; i < fsize / 2; i++) {
        char temp = data[i];
        data[i] = data[fsize - 1 - i];
        data[fsize - 1 - i] = temp;
    }

    // 写入反转后的数据
    fwrite(data, 1, fsize, fh1);

    // 释放资源
    free(data);
    fclose(fh);
    fclose(fh1);

    return 0;
}

方案2:分块读写(适合超大文件)

如果文件特别大(比如几GB),一次性分配内存也可能有压力,分块处理每次仅占用固定大小内存,更高效:

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

#define BLOCK_SIZE 4096 // 4KB块大小,可按需调整

int main()
{
    FILE *fh = fopen("vid.mp4", "rb");
    FILE *fh1 = fopen("vid1.mp4", "wb");

    if (!fh || !fh1) {
        perror("文件打开失败");
        return 1;
    }

    // 获取文件大小,用于定位读取位置
    fseek(fh, 0, SEEK_END);
    long fsize = ftell(fh);
    fseek(fh, 0, SEEK_SET);

    char *block = (char*)malloc(BLOCK_SIZE);
    if (!block) {
        perror("内存分配失败");
        fclose(fh);
        fclose(fh1);
        return 1;
    }

    // 从文件末尾往回读,每次读取一块后反转写入
    long pos = fsize;
    while (pos > 0) {
        long read_len = pos > BLOCK_SIZE ? BLOCK_SIZE : pos;
        fseek(fh, pos - read_len, SEEK_SET);
        size_t read_bytes = fread(block, 1, read_len, fh);
        if (read_bytes != read_len) {
            perror("块读取失败");
            break;
        }

        // 反转当前块
        for (long i = 0; i < read_len / 2; i++) {
            char temp = block[i];
            block[i] = block[read_len - 1 - i];
            block[read_len - 1 - i] = temp;
        }

        fwrite(block, 1, read_len, fh1);
        pos -= read_len;
    }

    free(block);
    fclose(fh);
    fclose(fh1);

    return 0;
}

额外注意事项

  • 不要硬编码文件大小,用fseek+ftell动态获取,适配文件变化。
  • 必须检查所有IO操作和内存分配的返回值,避免异常崩溃。
  • 反转后的文件建议保留原后缀,避免系统格式识别错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 00:23:19