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

为何不存储文件描述符会触发stack smashing detected错误?

栈溢出错误原因及存文件描述符变量后“正常”的本质

1. 直接运行报错的根本原因

你的代码里char buffer;只分配了1字节的栈空间,但read(3, &buffer, 2)要求读取2字节数据到这个缓冲区。这会直接触发缓冲区溢出,超出的1字节会覆盖栈上相邻的内存区域——而GCC默认启用了-fstack-protector编译选项,会在栈帧中插入栈保护cookie(一个随机校验值),当溢出覆盖这个cookie时,程序退出前的检测机制会发现关键数据被篡改,从而抛出*** stack smashing detected ***错误。

虽然文件读写操作已经完成,但栈内存的破坏已经发生,程序终止时的保护机制会触发这个报错。

2. 存文件描述符到变量后“正常”的本质

你提到将文件描述符存入变量后程序不再报错,这不是因为“存变量”修复了问题,而是栈内存布局发生了变化:

  • 当你声明额外的int类型变量(每个占4字节栈空间),这些变量会被分配在buffer的内存之后。此时read溢出的1字节会写入这些变量的内存区域,而非直接覆盖栈保护cookie或函数返回地址这类关键数据。
  • 这种情况下栈保护机制没检测到核心数据被篡改,所以程序不会触发错误,但缓冲区溢出的问题依然存在,属于未定义行为——如果后续代码用到被篡改的变量,或者栈布局稍有变动,依然可能出现崩溃、数据错乱等问题。

3. 正确的修复方式

要彻底解决问题,需给缓冲区分配足够容纳数据的空间,同时规范处理系统调用的返回值(不要假设文件描述符固定为3、4):

#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>

int main(void) {
    // 分配2字节缓冲区,刚好匹配要读取的数据量
    char buffer[2];
    int fd_source = open("source.txt", O_RDONLY);
    if (fd_source == -1) {
        perror("打开source.txt失败");
        return 1;
    }

    int fd_target = open("target.txt", O_WRONLY);
    if (fd_target == -1) {
        perror("打开target.txt失败");
        close(fd_source);
        return 1;
    }

    ssize_t bytes_read = read(fd_source, buffer, 2);
    if (bytes_read == -1) {
        perror("读取失败");
    } else {
        // 只写入实际读取到的字节数
        write(fd_target, buffer, bytes_read);
    }

    close(fd_source);
    close(fd_target);
    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 22:05:37