如何解释内存地址?

时间:2017-03-23 09:59:51

标签: linux memory memory-management linux-kernel

当我打印出不同内存区域的地址时,我得到的值如0xda2280,0x7f8a494f9010等。这些指向内存中的不同字节。

1)但为什么范围如此之大?中间的每个地址都是可寻址的,这意味着我的内存超过140TB。我怎么解释这个?

2)大多数时候地址被分组在高地址和低地址(堆和堆栈)中。但有时我看到三个不同的区域,明显分开。这第三个记忆区是什么?

2 个答案:

答案 0 :(得分:1)

查看/proc/<pid>/smaps以查看进程已映射的所有不同地址范围。您会发现像初始化的全局变量之类的地址对应于映射到可执行文件本身的范围,堆栈映射中的堆栈变量以及堆映射中的小型malloced数据。共享库中函数的地址(例如&printf)将出现在该lib的文本段映射中。

有多种方法可以创建映射范围,例如brk()可以更改堆大小,mmap()可以将文件的一部分映射到内存中。后者是可执行文件和共享库的代码和数据段如何放入内存。

不是一个接一个地分配范围,而是不同类型的分配具有不同的区域。这就是为什么你看到分散在整个64位地址空间的范围。

大型malloc可能具有与小型地址不同的地址的原因是因为malloc如何分配内存。小分配通常来自堆,在典型的x86_64系统中,堆位于较低的地址。但是大量的分配不是来自堆。如果确实如此,那么当它被释放时,就会出现这个巨大的漏洞,而它之前和之后仍然分配着其他数据。效率低下。这是一个被称为碎片的问题的一部分。因此,非常大的分配使用mmap()来映射新的内存区域,仅用于一个分配。这个被称为“匿名映射”的地方将来自与堆不同的区域,因此您获得的地址看起来不同。

答案 1 :(得分:0)

您看到的内存地址只是虚拟的。操作系统有一个内存管理器,它基本上是应用程序使用的虚拟地址和物理内存之间的动态映射。

此外,为了提高安全性,每次执行应用程序时,其中一些内存地址可能是随机的,这使得更难以利用缓冲区溢出错误等。