分配() |堆栈和堆位置的内存地址长度差异 | C编程
malloc() | difference in memory address length of stack and heap locations | C programming
我正在学习c程序的内存管理。我有一个很好的疑问。 (Ubuntu OS)
我的疑问:
我想知道位于栈内和堆内的 数据的地址 。但是当我尝试打印这些地址时,我发现地址的长度是不同的! 这里的问题是为什么显示的栈地址比堆地址长?
我所知道的:
- 每个进程的堆栈内存是固定的,小于堆内存。
- malloc() 在堆上分配内存
- 局部变量入栈
我把我的demo代码放在这里,方便大家解答我的疑惑
#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..我在某处读过这个)那么它也应该具有相同的长度。
好的。请帮我弄清楚我的记忆概念crystal。
注意:如果我的疑问非常简单或愚蠢,那么至少也请让我知道我的演示代码中的内存分配是如何完成的,以及不同长度地址背后的魔法。
感谢阅读post。回答愉快!
您似乎正在使用 64 位地址,这意味着它们打印为 最多 16 个十六进制字符。您应该在左侧用零填充所有地址以达到 16 个字符。
0x0000000001ea2010: heap address
0x00007ffda62cb3c0: stack address
堆和栈都位于同一个虚拟 2^64 字节中space。
没有标准。
但是,通常情况下,堆会向上增长而堆栈会向下增长。因此,从逻辑上讲,在起点处,Heap 的大小会更小,而 Stack 的大小会更大。
存在这种实现的原因是,它使程序较少有机会重叠静态内存与动态内存。
上面有人提到了虚拟地址和物理地址。从上下文来看,进程中的每一块内存都是一个虚拟地址,因此,试图解释 BUDDY 算法充其量是一种冗余,最坏的情况是无关紧要。
假设你住在一条长街上。你住在街道的南端,房子地址是1、2、3。
假设这条街向北延伸一英里。想象一下,在街道的北端,地址是 998、999、1000。
想象一下,到目前为止,只开发了街道的南北两端。从地址20到地址990都是未开发的空地
但是在你的街道尽头有很多 activity。新买家购买 20 到 30 号地块并开始在其上建造房屋。
同时,在街道的北端,没有那么多 activity。看起来 989 和 990 批次已经售出,那里正在建造一些东西。
那么,哪里有更大的"pool"未开发地块?在街道的北端还是南端?
到目前为止,街道南端的房屋数量(1-20 套,并且还在增加)多于街道北端的房屋数量(990-1000 套)。到目前为止,街道南端的增长速度也更快。 (南端有 10 个在建地块,北端有 2 个。)
然而,街道北端的地址(以 9 开头的 3 位数字,或 4 位数字)比南端的地址(2 位数字)大。这是什么意思? (答案:它实际上没有任何意义。)
您在 printf 中的格式字符串指定跳过前导零,这是默认设置。您需要添加所需的打印地址长度,如 %016p、%016x 或 %016X(如果您需要大写十六进制字符)。
如您正确假设的那样,所有指针的长度必须相同。
鉴于您 运行 Ubuntu,我假设您 运行 在 x86 或 x86-64 平台上。假设这是真的,您的程序布局如下所示:
+-----------------------------+
High Address: | Command-line arguments |
| and environment variables |
+-----------------------------+
| Stack |
| | |
| V |
| |
| ^ |
| | |
| Heap |
+-----------------------------+
| Uninitialized Data |
+-----------------------------+
| Initialized Data |
+-----------------------------+
| Program Text |
Low Address: | (machine code) |
+-----------------------------+
堆栈从高地址开始并增长 "downwards"(向地址递减),而堆从相当低的地址开始并增长 "upwards"(向递增地址)。 %p
转换说明符不打印地址值中的前导零;如果是这样,您的地址将类似于
0x0000000001ea2010: heap address
0x00007ffda62cb3c0: stack address
两个地址的长度确实相同,只是没有显示前导零。
我正在学习c程序的内存管理。我有一个很好的疑问。 (Ubuntu OS)
我的疑问:
我想知道位于栈内和堆内的 数据的地址 。但是当我尝试打印这些地址时,我发现地址的长度是不同的! 这里的问题是为什么显示的栈地址比堆地址长?
我所知道的:
- 每个进程的堆栈内存是固定的,小于堆内存。
- malloc() 在堆上分配内存
- 局部变量入栈
我把我的demo代码放在这里,方便大家解答我的疑惑
#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..我在某处读过这个)那么它也应该具有相同的长度。
好的。请帮我弄清楚我的记忆概念crystal。
注意:如果我的疑问非常简单或愚蠢,那么至少也请让我知道我的演示代码中的内存分配是如何完成的,以及不同长度地址背后的魔法。
感谢阅读post。回答愉快!
您似乎正在使用 64 位地址,这意味着它们打印为 最多 16 个十六进制字符。您应该在左侧用零填充所有地址以达到 16 个字符。
0x0000000001ea2010: heap address
0x00007ffda62cb3c0: stack address
堆和栈都位于同一个虚拟 2^64 字节中space。
没有标准。
但是,通常情况下,堆会向上增长而堆栈会向下增长。因此,从逻辑上讲,在起点处,Heap 的大小会更小,而 Stack 的大小会更大。
存在这种实现的原因是,它使程序较少有机会重叠静态内存与动态内存。
上面有人提到了虚拟地址和物理地址。从上下文来看,进程中的每一块内存都是一个虚拟地址,因此,试图解释 BUDDY 算法充其量是一种冗余,最坏的情况是无关紧要。
假设你住在一条长街上。你住在街道的南端,房子地址是1、2、3。
假设这条街向北延伸一英里。想象一下,在街道的北端,地址是 998、999、1000。
想象一下,到目前为止,只开发了街道的南北两端。从地址20到地址990都是未开发的空地
但是在你的街道尽头有很多 activity。新买家购买 20 到 30 号地块并开始在其上建造房屋。
同时,在街道的北端,没有那么多 activity。看起来 989 和 990 批次已经售出,那里正在建造一些东西。
那么,哪里有更大的"pool"未开发地块?在街道的北端还是南端?
到目前为止,街道南端的房屋数量(1-20 套,并且还在增加)多于街道北端的房屋数量(990-1000 套)。到目前为止,街道南端的增长速度也更快。 (南端有 10 个在建地块,北端有 2 个。)
然而,街道北端的地址(以 9 开头的 3 位数字,或 4 位数字)比南端的地址(2 位数字)大。这是什么意思? (答案:它实际上没有任何意义。)
您在 printf 中的格式字符串指定跳过前导零,这是默认设置。您需要添加所需的打印地址长度,如 %016p、%016x 或 %016X(如果您需要大写十六进制字符)。
如您正确假设的那样,所有指针的长度必须相同。
鉴于您 运行 Ubuntu,我假设您 运行 在 x86 或 x86-64 平台上。假设这是真的,您的程序布局如下所示:
+-----------------------------+
High Address: | Command-line arguments |
| and environment variables |
+-----------------------------+
| Stack |
| | |
| V |
| |
| ^ |
| | |
| Heap |
+-----------------------------+
| Uninitialized Data |
+-----------------------------+
| Initialized Data |
+-----------------------------+
| Program Text |
Low Address: | (machine code) |
+-----------------------------+
堆栈从高地址开始并增长 "downwards"(向地址递减),而堆从相当低的地址开始并增长 "upwards"(向递增地址)。 %p
转换说明符不打印地址值中的前导零;如果是这样,您的地址将类似于
0x0000000001ea2010: heap address
0x00007ffda62cb3c0: stack address
两个地址的长度确实相同,只是没有显示前导零。