gpt4 book ai didi

c - 由于对齐差异,此程序是否仅在 x32 上崩溃?

转载 作者:太空宇宙 更新时间:2023-11-03 23:23:47 24 4
gpt4 key购买 nike

以下代码摘自here :

#include<stdio.h>

int main()
{
char i = 30;
char j = 123;
char* p = &i;
printf("pointer points to: %p\n", p);
void* q = p;
int * pp = q; /* unsafe, legal C, not C++ */

printf("%d %d\n",i,j);
*pp = -1; /* overwrite memory starting at &i */
printf("%d %d\n",i,j);
printf("pointer points to: %p\n", p);
printf("%d\n", *p);
}

在我的 x32 Linux 机器上,它在最后一行崩溃。在 x64 Linux 上它不会崩溃。是因为指针在 x32 上是 4 个字节,在 x64 上是 8 个字节,并且由于对齐要求,在 x64 上 char jchar *p 之间可能有一个最大 6 字节的空洞被 *pp = -1 覆盖的机器,因此 *p 没有任何反应,但在 x32 机器上,空洞最多只有 2 个字节,因此 *pp = -1 会覆盖 char *p 的前两个字节,从而在取消引用时导致段错误?这个推理是正确的还是完全愚蠢的?

最佳答案

推理不白痴,但不保证正确。

函数栈的布局并不像你想象的那么固定。虽然堆栈指针寄存器只允许有地址 mod 4 或 mod 8,但取决于对齐方式,编译器不需要遵循特定的对齐方式。甚至不能保证数据在堆栈中的某个位置。它可能完全驻留在寄存器中!

您想到的堆栈对齐是过程调用标准的一部分,它说明了在一个函数调用另一个函数并希望通过堆栈传输数据之前堆栈必须是什么样子。只有在这种情况下,编译器才需要对齐和填充数据,并确保作为参数传递的指针地址位于 4/8 字节边界上。

例如:您的 x64 可执行文件可能会运行,只是因为编译器将 p 保存在寄存器中而不是堆栈中,因此覆盖堆栈不会影响 p,即使您将整个堆栈 memset 为零。 p 始终是可以取消引用的有效地址。

因此,您的代码也可以在 32 位机器上正常运行,或者在 64 位机器上崩溃。编译器及其优化设置比架构更能决定结果。

关于c - 由于对齐差异,此程序是否仅在 x32 上崩溃?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32094885/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com