为何同一变量var的内存地址在两次运行中发生变化?
问题描述
我正在通过实验学习指针以加深理解,遇到了这样的情况:我声明了变量var和两个指针,在打印var的地址并与两个指针对比时,发现即使核心声明语句一致,var的地址却在两个值间变化。
第一次运行情况
代码:
#include <stdio.h> int main () { int var; int *ptr; int **pptr; var = 3000; ptr = &var; pptr = &ptr; printf("Address of var = %p\n", &var ); printf("Value available at ptr = %p\n", ptr ); // should be equal to address of Var printf("Address of ptr = %p\n", &ptr ); // should be equal to address of ptr printf("value available at pptr = %p\n", pptr); // should be equal to address of ptr printf("address of pptr = %p\n", &pptr ); // should be equal to address of pptr return 0; }
输出:
Address of var = 0061FF1C Value available at ptr = 0061FF1C Address of ptr = 0061FF18 value available at pptr = 0061FF18 address of pptr = 0061FF14
第二次运行情况
代码:
#include <stdio.h> int main () { int var; int *ptr; int **pptr; var = 3000; ptr = &var; pptr = &ptr; printf("Address of var = %p\n", &var ); printf("Value available at ptr = %p\n", ptr ); // should be equal to address of Var printf("value available at pptr = %p\n", pptr); // should be equal to address of ptr return 0; }
输出:
Address of var = 0061FF18 Value available at ptr = 0061FF18 value available at pptr = 0061FF14
我原本预期var的地址每次运行都相同,请问为何会发生变化?
原因解析
1. 地址空间随机化(ASLR)的作用
现代主流操作系统(Windows、Linux、macOS等)默认开启**地址空间随机化(ASLR)**机制。该机制会在每次程序启动时,随机调整进程内存中栈、堆、动态链接库等区域的起始地址,以此防范缓冲区溢出等依赖固定内存地址的攻击手段。这直接导致同一程序每次运行时,局部变量所在的栈地址不会固定。
2. 栈帧布局的差异
两次运行的代码中,printf调用的数量不同,这会改变函数栈帧的结构。函数调用时,栈上会存放参数、返回地址、寄存器备份等数据,printf数量越多,栈上占用的临时空间就越多,编译器分配局部变量的位置会随之调整。第一次代码有5个printf,第二次只有3个,栈帧的大小和布局变化,最终导致var的地址出现差异。
此外,C语言标准并没有对局部变量的内存地址作出固定的规定,编译器和操作系统完全有权根据运行环境、代码结构调整变量的分配位置,所以你预期地址固定的想法并不符合实际的程序运行机制。
内容的提问来源于stack exchange,提问作者Bemin Dawoud
相关产品推荐
相关产品推荐

