这是代码:
#include <stdio.h>
#include <stdlib.h>
int main() {
int a = 10;
int b = 20;
//printf("\n&a value %p", &a);
int* x = &b;
x = x + 1;
*x = 5;
printf("\nb value %d", b);
printf("\na value %d", a);
}
我想用 b 地址覆盖 a 以测试 c 溢出,但是当我注释第 5 行(printf 函数)时,我无法在 a 中写入 5 个。而如果我打印地址,我可以在一个地址中写五个。 为什么? 抱歉我的英语不好,谢谢。
最佳答案
发生这种情况的原因是,所有普通编译器都将具有自动存储持续时间的对象(在 block 内声明的非 static
或 extern
的对象)存储在堆栈上。您的编译器将a
“推”到堆栈上,这意味着它将a
写入堆栈指针指向的内存位置,然后递减该指针。 (递减指针会增加堆栈,因为堆栈沿着内存地址减少的方向增长。堆栈可以朝另一个方向定向,但您观察到的行为强烈表明您的系统使用向下增长的共同方向。)然后您的编译器将 b
压入堆栈。因此,b
最终位于 a
下面的内存地址。
当您获取 b
的地址并加一时,就会生成 a
所在的内存地址。当您使用该地址分配 5 时,该值将写入 a
所在的位置。
C 标准均未定义此行为。这是您使用的特定编译器和编译时使用的开关的结果。
您的编译可能很少或没有优化。启用优化后,许多编译器会通过删除不必要的步骤(实质上用快捷方式替换它们)来简化代码,以便 20 和 10 实际上不会存储在堆栈中。优化的一个可能结果是打印“20”和“10”,并且您对 *x
的分配无效。然而,C 标准并没有说明当您以这种方式使用 *x
时必须有什么行为,因此结果仅由您使用的特定编译器以及您提供的输入开关决定它。
关于c - 奇怪的行为c自愿溢出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47091859/