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

调用read系统调用读取文件时,为何要将缓冲区buf设为'\0'?

为什么读取文件后、关闭文件描述符前要给缓冲区buf设置'\0'?

示例代码如下:

ssize_t read_textfile(const char *filename, size_t letters)
{
    int fd;
    int i, y;
    char *buf;
    if (!filename)
        return (0);
    fd = open(filename, O_RDONLY);
    if (fd < 0)
        return (0);
    buf = malloc(sizeof(char) * letters);
    if (!buf)
        return (0);
    i = read(fd, buf, letters);
    if (i < 0)
    {
        free(buf);
        return (0);
    }
    buf[i] = '\0';        // 疑问指向的代码行
    close(fd);
    y = write(STDOUT_FILENO, buf, i);
    if (y < 0)
    {
        free(buf);
        return (0);
    }
    free(buf);
    return (y);
}

原因解析

这段代码里给buf[i] = '\0'的操作,本质是防御性编程的习惯,具体原因有这几点:

  • 防止后续字符串操作出问题:当前代码用write输出时,明确指定了写入长度是i(实际读取的字节数),确实不需要依赖'\0'。但如果之后代码有修改(比如改成用strlen(buf)获取长度、或者用puts这类依赖字符串结尾的函数),没有'\0'就会读取到内存里的垃圾数据,甚至触发越界访问的未定义行为。提前加上终止符,能避免这类后续维护时的潜在bug。
  • 处理malloc未初始化的内存:malloc分配的内存是未清零的,里面会有随机的垃圾值。如果文件内容长度小于letters,read只填满了前i个字节,剩下的内存空间是脏数据。加上'\0'后,即使后续有调试打印buf的操作,也只会显示到实际读取的内容为止,不会输出垃圾。
  • 符合C字符串规范:C语言中标准字符串必须以'\0'结尾,把缓冲区按字符串的标准来处理,是一种良好的编程习惯,能减少因“非标准字符串”引发的意外问题。

代码隐患提醒

这段代码存在一个潜在bug:如果read刚好读取了letters个字节(即i == letters),那么buf[i] = '\0'会访问malloc分配的内存之外的空间,属于越界写入,会触发未定义行为。正确的做法应该是给malloc多分配一个字节的空间,用来存储终止符:

buf = malloc(sizeof(char) * (letters + 1));

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 14:57:22