为何不存储文件描述符会触发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
相关产品推荐
相关产品推荐

