虚拟地址:四个中的多个对齐 - 写入地址"介于"

时间:2016-05-05 22:08:59

标签: c paging memory-address virtual-memory

执行某些程序时,我意识到虚拟地址总是四的倍数(假设32位虚拟地址)。例如:

int main()
{
   int a = 7;
   int b = 10;
   printf("%p %p", &a, &b);
}

将提供类似的内容:

  • xff86c930 0xff86c934
  • xfff58f80 0xfff58f84
  • ...

它们之间的区别总是四个。 现在我尝试了这个:

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来自哪里?是否会出现页面错误?

1 个答案:

答案 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评论的意思。