这是代码:
#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);
}
我想覆盖a和b地址来测试c溢出但是当我评论第5行(printf功能)时我不能写入5。如果我打印一个地址,我可以写一个五。 为什么? 对不起我的英文,谢谢你。
答案 0 :(得分:1)
发生这种情况的原因是,所有正常编译器都会在堆栈上存储具有自动存储持续时间(在块中声明为非static
或extern
的对象)的对象。您的编译器将a
“推送”到堆栈上,这意味着它将a
写入堆栈指针指向的内存位置,然后递减指针。 (减少指针会增加堆栈,因为堆栈会朝着减少内存地址的方向增长。堆栈可以朝向另一个方向,但您观察到的行为强烈建议您的系统使用向下增长的共同方向。)然后,编译器将b
推入堆栈。因此,b
最终位于a
下方的内存地址。
当您获取b
的地址并添加一个时,会产生a
所在的内存地址。当您使用该地址分配5时,该值被写入a
所在的位置。
这种行为都不是由C标准定义的。这是您使用的特定编译器和编译的开关的结果。
您可能很少或根本没有优化编译。启用优化后,许多编译器会通过删除不必要的步骤(基本上用快捷方式替换它们)来简化代码,因此20和10实际上并不存储在堆栈中。优化的可能结果是打印“20”和“10”,您对*x
的分配无效。但是,C标准没有说明以这种方式使用*x
时必须采取的行为,因此结果仅由您使用的特定编译器以及您提供的输入开关确定。
答案 1 :(得分:-1)
x = x + 1;
之后,x
包含您不拥有的地址。通过执行*x = 5;
,您尝试写入某些可能无法访问的位置。从而导致UB。没有更多的理由可以解释。