虚拟地址:四个对齐的倍数 - 写入地址 "in between"
Virtual addresses: multiple of four aligned - writing to address "in between"
在执行某些程序时,我意识到虚拟地址总是四的倍数(假设 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哪里来的?会不会出现页面错误?
把y当成int(64位系统危险)
int yi = (int)y;
将其地址递减为整数而不是指针 - 将导致它变得未对齐。
yi--;
将新整数硬编码为指针 - 现在使用该指针可能非常危险
y = (int*)yi;
取消引用未对齐的指针。这将根据内存控制器在不同的系统上做不同的事情。充其量,它会立即出现段错误,因此您无法做出任何假设。
printf("%p %p: %d\n", &b, y, *y);
在未对齐的内存上踩点更多的乐趣 - 为什么不呢。
*y = 7;
2807从哪里来?它是内存控制器想要给你的任何东西。也许是栈前面的垃圾值,也许是下面这个词的桶移位值,完全是系统的选择。
这就是@kaylum 在他的 UB 评论中的意思。
在执行某些程序时,我意识到虚拟地址总是四的倍数(假设 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哪里来的?会不会出现页面错误?
把y当成int(64位系统危险)
int yi = (int)y;
将其地址递减为整数而不是指针 - 将导致它变得未对齐。
yi--;
将新整数硬编码为指针 - 现在使用该指针可能非常危险
y = (int*)yi;
取消引用未对齐的指针。这将根据内存控制器在不同的系统上做不同的事情。充其量,它会立即出现段错误,因此您无法做出任何假设。
printf("%p %p: %d\n", &b, y, *y);
在未对齐的内存上踩点更多的乐趣 - 为什么不呢。
*y = 7;
2807从哪里来?它是内存控制器想要给你的任何东西。也许是栈前面的垃圾值,也许是下面这个词的桶移位值,完全是系统的选择。
这就是@kaylum 在他的 UB 评论中的意思。