缓冲区溢出实验中栈内变量间存在“间隙”的原因咨询
缓冲区溢出实验中栈变量间隙的原因解答
首先看你提供的测试代码:
#include <stdlib.h> #include <unistd.h> #include <stdio.h> int main(int argc, char **argv) { int modified; char buffer[64]; modified = 0; gets(buffer); if(modified != 0) printf("Changed!"); else printf("Not changed!"); }
你的实验场景:
我正在开展缓冲区溢出实验,编译命令为
gcc -g -fno-stack-protector test1.c -o test1。当程序执行到if(modified != 0)时,基址指针为0x00007fffffffdfe0,基址指针下方是存储整数0的4字节(对应变量modified),但char buffer[64]并未紧跟在int modified之后,中间存在4字节0与0x00007fff的“间隙”,之后才是我输入的64个A。
问题解答
这个间隙其实是x86-64平台的栈内存对齐机制导致的,具体细节如下:
- x86-64架构遵循System V应用二进制接口(ABI)规范,其中明确要求函数调用时栈指针必须保持16字节对齐。哪怕你关闭了栈保护(
-fno-stack-protector),编译器依然会严格遵守这个底层硬件和ABI的规则。 - 你的变量
modified是4字节的int类型,而buffer是64字节的字符数组。编译器在分配栈空间时,会从高地址向低地址依次安排变量,但为了让后续的buffer以及整个栈帧满足16字节对齐要求,会在modified和buffer之间自动插入4字节的填充(也就是你看到的“间隙”)。这样modified(4字节)+填充(4字节)+buffer(64字节)的总长度是72字节,能完美契合栈对齐的要求。 - 另外,编译器通常会优先分配小尺寸的非数组变量(比如这里的
modified),再分配数组类的大块内存,这种分配顺序加上对齐要求,就必然会产生这段填充间隙。
本质上,这段间隙是编译器为了保证内存访问的效率和正确性,遵循平台规范插入的填充字节,和栈保护没有关系——哪怕你关闭了栈保护,对齐规则依然会生效。
内容的提问来源于stack exchange,提问作者Carol Ward
相关产品推荐
相关产品推荐

