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

C语言读取文件添加空终止符后仍出现尾端乱码的问题求助

解决Windows下C语言读取着色器文件末尾出现垃圾字符的问题

你的问题根源在于文本模式下的换行符转换:Windows系统中,文本文件的换行符是CR-LF(\r\n),当你用"r"模式打开文件时,C标准库会自动把\r\n转换成单个\n,导致实际读取到缓冲区的字节数比ftell()获取的原始文件大小少。而你直接用原始文件长度设置空终止符的位置,缓冲区中未被文件内容覆盖的部分(对应被转换掉的\r的字节位置)会残留malloc时的随机垃圾数据,最终打印时就会出现奇怪的字符。

两种可行的解决方法:

方法1:用二进制模式读取文件

把文件打开模式改成"rb",这样标准库不会转换任何字符,读取的内容和文件原始字节完全一致,ftell()的长度和fread()实际读取的字节数也会相等,后续设置空终止符的逻辑就能正常工作。

修改后的代码:

char* parse_shader(const char* path)
{
    char* buffer = 0;
    long length = 0;
    FILE* source = fopen(path, "rb"); // 切换为二进制模式
    if(!source)
        ERROR_RETURN(NULL, "Failed to load source: %s\n", path);
    
    fseek(source, 0, SEEK_END);
    length = ftell(source);
    fseek(source, 0, SEEK_SET);
    buffer = malloc(length + 1);
    if(!buffer)
        ERROR_RETURN(NULL, "Failed to allocate memory for file: %s\n", path);
    fread(buffer, 1, length, source);

    buffer[length] = '\0';

    fclose(source);

    return buffer;
}

注:OpenGL着色器编译器完全兼容包含\r的换行符,不用担心语法问题。

方法2:依赖fread()的实际读取字节数设置终止符

如果你需要保持文本模式(比如要处理其他文本转换逻辑),不要用ftell()的结果来设置空终止符,而是用fread()的返回值——这个值才是实际写入缓冲区的字节数。

修改后的代码:

char* parse_shader(const char* path)
{
    char* buffer = 0;
    long length = 0;
    FILE* source = fopen(path, "r");
    if(!source)
        ERROR_RETURN(NULL, "Failed to load source: %s\n", path);
    
    fseek(source, 0, SEEK_END);
    length = ftell(source);
    fseek(source, 0, SEEK_SET);
    buffer = malloc(length + 1);
    if(!buffer)
        ERROR_RETURN(NULL, "Failed to allocate memory for file: %s\n", path);
    size_t bytes_read = fread(buffer, 1, length, source); // 捕获实际读取的字节数

    buffer[bytes_read] = '\0'; // 用实际读取数设置终止符

    fclose(source);

    return buffer;
}

这种方式下,缓冲区末尾多余的空间不会被访问到,自然不会出现垃圾字符。

额外提示

  • 用ftell()获取文本文件长度本身就不可靠,因为文本模式下文件指针的偏移量和实际字节数没有固定对应关系,二进制模式才是正确的做法。
  • 记得在使用完返回的缓冲区后调用free(),避免内存泄漏。

内容的提问来源于stack exchange,提问作者Dr-Galunga

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 23:12:54