gpt4 book ai didi

c - c中的堆栈内存布局

转载 作者:太空宇宙 更新时间:2023-11-04 01:54:54 24 4
gpt4 key购买 nike

为了学习C语言的栈指针,我写了一个小程序,通常栈指针指向RAM的最后一个地址。例如,我在 Linux 中运行这段代码,它在最后一个地址 (0x7fffffffffff) 中有堆栈指针,但变量存储在这些地址中(对于这个程序):

c --> 0x7ffc67ca5c94
b --> 0x7ffc67ca5c98
a --> 0x7ffc67ca5c9c

代码:

void fun(int *ptr)
{
printf("c --> %p\n",ptr);
ptr++;
printf("b --> %p\n",ptr);
ptr++;
printf("a --> %p\n",ptr);
}

int main()
{
int a = 10,b = 20,c = 30;
printf("%p %p %p\n",&a,&b,&c);
fun(&c);
return 0;
}

这个程序的输出:

0x7ffc67ca5c9c     0x7ffc67ca5c98    0x7ffc67ca5c94
c --> 0x7ffc67ca5c94
b --> 0x7ffc67ca5c98
a --> 0x7ffc67ca5c9c

我的问题是:

  1. 为什么变量没有存储在堆栈帧的最后一部分 (0x7fffffffffff) 中,它跳过了一些内存位置并被存储?这种行为有什么正当理由吗?

  2. 为什么栈指针地址有六个字节?

我正在使用带有 32 位 GCC 编译器的 64 位机器。

最佳答案

which has the stack pointer in last address (0x7fffffffffff)

如果运行 32 位进程,在执行 通常 2GB/2GB 拆分时,最后地址(减去保留区域)将为 0x7fff ffff。但是 32 位 Linux 通常只保留 1GB 的内核地址区域,因此堆栈实际上将从 0xc000 0000 (TASK_SIZE) 开始。

您在这里看到的是 x64 地址空间布局的奇怪拆分。在这里,确实用户地址空间结束于 0x0000 7fff ffff ffff0xffff ff80 0000 0000 及以上保留给内核。

当前的 MMU 实际上强制执行此操作,0xfffe ff80 0000 0000 或类似地址不是有效地址,位 47-63 必须等于以形成 Canonical Form Address

Why the stack pointer address has six bytes?

从您的程序输出来看,它看起来不像。您正在打印每个变量在堆栈中占用的大小,而不是指针大小。 printf() 中的六字节地址实际上是 64 位地址,前导零被截断(感谢 @Jonathan Leffler 发现了这一点)。

的确,sizeof(int *) == 8,但是sizeof(int) == 4,因为即使是 64 位 Linux 也有 32bit ints (只有 long 是 64 位)。不过,很容易忽略这一点。

Why are the variables not stored in last section of the stack frame (0x7fffffffffff) which skips some memory locations and gets stored? Any valid reason for such behavior?

如果你看here ,在用户堆栈开始之前,有很多东西进入该地址空间。由于您可能需要整个页面来保护此代码,因此可能会有一些开销。添加库启动代码,您可能会获得相当多字节的内存。

那里的大部分代码可能是从父进程继承的写时复制(甚至只读)。

编辑:在 x64 上,任何内核导出的代码都可能进入更高的内存区域。不要声称我没有验证过的东西 ;-)。

附带说明:当我在 64 位 FreeBSD 10.2 上编译和运行您的代码时,我得到了这个

0x7fffffffe5c8     0x7fffffffe5c4    0x7fffffffe5c0
c --> 0x7fffffffe5c0
b --> 0x7fffffffe5c4
a --> 0x7fffffffe5c8

这与您的输出类似,尽管 FreeBSD 似乎对堆栈的定位不同。

在 32 位模式下运行,我得到这个:

0xffffd788     0xffffd784    0xffffd780
c --> 0xffffd780
b --> 0xffffd784
a --> 0xffffd788

后者解释起来可能真的很有趣(例如,我的内核地址空间在哪里?)。

关于c - c中的堆栈内存布局,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35884573/

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