我正在学习c程序的内存管理 . 我已经怀疑了 . (Ubuntu OS)
我怀疑:
我想知道 data that lie inside stack and inside heap both 的地址 . 但是当我尝试打印这些地址时,我发现地址长度不同! Question here is why it is displaying stack address having more length than heap address?
我知道的 :
-
每个进程的堆栈内存是固定的,小于堆内存 .
-
malloc()在堆上分配内存
-
局部变量进入堆栈
我把我的演示代码放在这里,这样你就可以很好地回答我的疑问 .
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *ptr; // goes on stack
ptr = (int *)malloc(sizeof(int));
*ptr = 10; // 10 is stored on heap
printf("%p : heap address\n",ptr);
printf("%p: stack address\n",&ptr);
return 0;
}
输出:我的终端输出了以下输出
0x1ea2010 : heap address
0x7ffda62cb3c0: stack address
所以现在你可能会明白我在问什么 . 为什么堆栈地址的长度比堆长?堆是大量的内存,所以很明显它应该有更长的长度 .
如果堆栈和堆分配在相同的内存块中完成(根据现代OS ..我已经在某处读过),那么它也应该具有相同的长度 .
好的 . 请帮助我让我的记忆概念清晰明了 .
注意:如果我的疑问非常简单或愚蠢,那么至少请告诉我如何在我的演示代码中完成内存分配以及在不同长度的地址后面的魔术 .
感谢阅读这样的帖子 . 快乐回答!
5 回答
鉴于您正在运行Ubuntu,我假设您正在运行x86或x86-64平台 . 假设这是真的,你的程序布局看起来像这样:
堆栈从高地址开始并且增长"downwards"(朝向递减地址),而堆从相当低的地址开始并且增长"upwards"(朝向递增的地址) .
%p
转换说明符不在地址值中打印前导零;如果是的话,你的地址会是这样的两个地址实际上都是相同的长度,只是前导零没有显示 .
printf中的格式字符串指定跳过前导零,这是默认值 . 您需要在%016p,%016x或%016X中添加所需的打印地址长度(如果需要大写十六进制字符) .
正确地假设,所有指针的长度必须相同 .
您似乎正在使用64位地址,这意味着它们打印为 up to 16个十六进制字符 . 你应该在左侧用零填充所有地址,以达到16个字符 .
堆和堆栈都存在于相同的虚拟2 ^ 64字节空间中 .
没有标准 .
但是,通常情况下,当堆栈向下增长时,堆会增长 . 因此,从逻辑上讲,在起始点,Heap的大小会更小,而Stack会更大 .
之所以存在这样的实现,是因为它给程序提供了静态与动态内存重叠的可能性较小 .
上面提到的虚拟地址和物理地址 . 从上下文来讲,一个进程中的每一块内存都是一个虚拟地址,因此,试图解释BUDDY算法是最好的冗余,最坏的情况是不相关的 .
想象一下,你住在一条长街上 . 你住在街道的南端,房子的地址是1,2,3 .
想象一下,这条街向北延伸一英里 . 想象一下,在街道的北端,地址是998,999,1000 .
想象一下,到目前为止,只开发了街道的南北两端 . 从地址20到地址990只是未开发的空地 .
但是在你的街道尽头有很多活动 . 新买家在20到30之间买入并开始建造房屋 .
与此同时,在街道的北端,没有那么多的活动 . 看起来很多989和990已售出,并且正在那里建造一些东西 .
那么,哪里有未开发的更大的“池”?在街道的北端或南端?
到目前为止,街道南端(1-20,并且正在增长)的房屋数量多于街道北端(990-1000) . 到目前为止,街道南端的增长也更快 . (南端正在建设10个,北部为2个 . )
然而,街道北端的地址比南部(2位数)更大(3位数,从9位开始,或4位数) . 这是什么意思? (答案:这并不意味着什么 . )