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

为何fread()读取文件时返回额外垃圾值?

问题分析与解决方案

首先明确:你必须添加空终止符,原因是printf("%s")会持续输出直到遇到\0空字符,但通过fread读取的文件内容本身不包含这个终止符,而malloc分配的内存末尾是未初始化的随机值,这就是你看到垃圾值的原因。换行符越多垃圾值越多,是因为文本模式下文件的换行符转换(比如Windows下\n会被转为\r\n)导致计算的length和实际读取的字节数有偏差,进一步加剧了越界读取的问题。

具体修改方案(除calloc外)

方案1:分配内存时多留1字节,手动添加空终止符

修改你的代码,主要调整内存分配和添加终止符的步骤,同时补充必要的错误检查:

#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>

int main() {
    long length;
    char* content;
    FILE *file = fopen("text.txt", "rb"); // 用二进制模式打开,避免文本模式的换行转换问题
    if (file == NULL) { // 检查文件是否成功打开
        perror("Failed to open file");
        return 1;
    }
    fseek(file, 0, SEEK_END);
    length = ftell(file);
    if (length == -1) { // 检查ftell是否成功
        perror("Failed to get file length");
        fclose(file);
        return 1;
    }
    fseek(file, 0, SEEK_SET);
    content = (char *)malloc(length + 1); // 多分配1字节用于存储空终止符
    if (content == NULL) { // 检查内存分配是否成功
        perror("Failed to allocate memory");
        fclose(file);
        return 1;
    }
    size_t read_bytes = fread(content, 1, length, file);
    if (read_bytes != length) { // 检查实际读取的字节数是否符合预期
        fprintf(stderr, "Only read %zu bytes out of %ld\n", read_bytes, length);
    }
    content[read_bytes] = '\0'; // 用实际读取的字节数来设置终止符,更严谨
    printf("%s\n", content);
    free(content); // 记得释放内存
    fclose(file); // 关闭文件
    return 0;
}

关键修改点说明

  • 用"rb"二进制模式打开文件:避免Windows系统中文本模式下的换行符转换(\n转为\r\n),确保ftell获取的长度和实际文件字节数一致。
  • 分配length + 1字节的内存:预留空终止符的位置。
  • 添加content[read_bytes] = '\0';:用实际读取的字节数而非length来设置终止符,因为fread可能因为文件问题读取的字节数少于预期,这样更安全。
  • 补充错误检查:避免文件打开失败、内存分配失败等异常情况导致程序崩溃。

方案2:读取后直接在内存末尾覆盖(不推荐)

如果不想多分配内存,也可以在读取后将content的第length位设为\0,但这个操作存在风险——malloc分配的内存块后面的空间不属于程序,强行写入可能触发内存错误,因此仅在确认内存有额外可写空间时使用,优先推荐方案1。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 16:16:06