为何改变局部变量初始化顺序后auth_flag地址未变?
为什么调整局部变量声明顺序后,变量地址始终不变?
我读了《Hacking: the Art of the Exploit》这本书,里面的例子表明:当int类型变量auth_flag在char数组buffer_password[16]之前声明时,auth_flag的地址会高于buffer_password;如果把auth_flag放在数组之后声明,它的地址应该低于buffer_password。但我实际测试时,不管怎么调整这两个变量的声明顺序,auth_flag的地址都没变,这是为什么?
测试代码如下:
#include <stdio.h> #include <string.h> #include <stdlib.h> int check_authentication(char *password) { char buffer_password[16]; int auth_flag = 0; strcpy(buffer_password, password); if (strcmp(buffer_password, "brilling") == 0) auth_flag = 1; if (strcmp(buffer_password, "outgrabe") == 0) auth_flag = 1; return auth_flag; }
原因分析:
- 编译器内存布局优化:现代编译器(如GCC、Clang)会对栈上的局部变量做优化,不会严格遵循代码里的声明顺序分配空间。为了提升内存访问效率,编译器会把对齐要求相同、大小匹配的变量归置在一起,甚至调整位置减少内存碎片,所以你改声明顺序后,
auth_flag可能还是被放到了优化后的固定位置。 - 内存对齐规则:平台的内存对齐要求会约束变量位置。int类型一般要求4字节对齐,而
buffer_password[16]本身是16字节(天然满足对齐),编译器可能为了符合对齐规则,固定把int变量放在某个对齐后的地址上,不受声明顺序影响。 - 编译选项的差异:书中的例子大概率是基于旧版本编译器或关闭优化的编译环境。你可以尝试用
-O0(完全关闭优化)选项编译代码,再观察变量地址是否会随声明顺序变化——很多时候开启优化后,编译器会彻底打乱局部变量的声明顺序。 - 栈帧结构限制:函数的栈帧里除了局部变量,还有返回地址、栈基址(EBP/RBP)等固定结构。编译器会把局部变量统一分配在栈帧的特定区域,不会因为单个变量的声明顺序轻易改变整个栈帧的布局。
内容的提问来源于stack exchange,提问作者user22998702
相关产品推荐
相关产品推荐

