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
相关产品推荐
相关产品推荐

