执行某些程序时,我意识到虚拟地址总是四的倍数(假设32位虚拟地址)。例如:
int main()
{
int a = 7;
int b = 10;
printf("%p %p", &a, &b);
}
将提供类似的内容:
它们之间的区别总是四个。 现在我尝试了这个:
int main()
{
int a = 7;
int b = 10;
int *y = &b;
int yi = (int)y;
yi--;
y = (int*)yi;
printf("%p %p: %d\n", &b, y, *y);
*y = 7;
printf("%p: %d\n", y, *y);
}
一个示例输出是:
0xffe460a0 0xffe4609f:2807
0xffe4609f:7
这里发生了什么?当我尝试将某些内容写入不是四的倍数的地址时引用了什么?这2807来自哪里?是否会出现页面错误?
答案 0 :(得分:1)
将y作为int(在64位系统上很危险)
int yi = (int)y;
将其地址减小为整数而不是指针 - 将导致它变为未对齐。
yi--;
将新整数作为指针返回的硬代码 - 此指针现在使用
可能非常危险y = (int*)yi;
取消引用未对齐的指针。根据内存控制器的不同,这将在不同的系统上执行不同的操作。充其量,它会立即发生故障,因此您不做任何假设。
printf("%p %p: %d\n", &b, y, *y);
在未对齐的记忆中踩踏更多内容以获得乐趣 - 为什么不呢。
*y = 7;
2807来自哪里?这是内存控制器想要给你的东西。也许它是堆栈中较早的垃圾值,也许它是下面这个词的桶移位值,它完全是系统的选择。
这就是@kaylum对UB评论的意思。