我一直认为堆栈位于比图片2更高的堆位置。但我发现当我使用cpp(picture1)测试它时,有时堆地址会更高。我知道使用虚拟内存但我也想知道为什么堆栈和堆的虚拟地址不遵循picture2?非常感谢你!
答案 0 :(得分:1)
您的图表只是概念性的。它没有反映链接,动态加载,重定位和运行时内存分配的复杂性。
答案 1 :(得分:1)
实际上,堆数据不在最近的Linux系统上(可能在大多数其他桌面或服务器操作系统上)必然是连续的。 virtual address space(VAS)wikipage还有一个简化数字。
在Linux系统上,您可以试用proc(5)。尝试cat /proc/self/maps
在终端上显示(当前)cat
process的虚拟地址空间。另请尝试cat /proc/$$/maps
(获取当前shell的VAS)和(以root身份)cat /proc/$(pidof Xorg)/maps
(以获取Xorg服务器的VAS)。并尝试其他cat /proc/
some-pid /maps
以获取各种流程的各种代码。
其中一个解释是,malloc
有时会调用mmap(2),而不仅仅是sbrk(2)。特别是,大内存块的malloc
将使用mmap
(我认为"阈值"使用mmap
可能是malloc
{1}}几兆字节)。并且库和应用程序可以使用mmap
来访问某个文件。
并且mmap
正在使用ASLR,所以显然不会给出连续的内存段。当然,应用程序(或free
的实现)有时可以使用munmap
来释放内存。而dynamic linking(请参阅ld-linux(8)& dlopen(3) ...)也使用mmap
和munmap
。
所以虚拟地址空间可以(通常是)由许多不连续的内存段组成(有时数千个)。< / p>
BTW,多线程也需要几个内存段。通常每个线程都有自己的mmap
- 堆栈空间。
例如,我有一些mate-terminal
terminal emulator作为pid 2594的进程运行。它的进程有568个内存段(即/proc/2594/maps
中的行)。通过展示所有这些,我不会破坏这个答案。我输入此答案的firefox
浏览器进程在/proc/1604/maps
中有1229行,以下是其中一些:
27423e6e0000-27423e720000 r-xp 00000000 00:00 0
27423e720000-27423e730000 r-xp 00000000 00:00 0
27423e730000-27423e760000 r-xp 00000000 00:00 0
27423e760000-27423e780000 r-xp 00000000 00:00 0
27423e780000-27423e7c0000 r-xp 00000000 00:00 0
27423e7c0000-27423e7d0000 r-xp 00000000 00:00 0
27423e7d0000-27423e7e0000 ---p 00000000 00:00 0
27423e7e0000-27423e7f0000 r-xp 00000000 00:00 0
7efed334d000-7efed3357000 r--p 00172000 08:01 11275829 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.23
7efed3357000-7efed3359000 rw-p 0017c000 08:01 11275829 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.23
7efed3359000-7efed335c000 rw-p 00000000 00:00 0
7efed335c000-7efed335f000 r-xp 00000000 08:01 1704007 /lib/x86_64-linux-gnu/libdl-2.24.so
7efed335f000-7efed355e000 ---p 00003000 08:01 1704007 /lib/x86_64-linux-gnu/libdl-2.24.so
7efed355e000-7efed355f000 r--p 00002000 08:01 1704007 /lib/x86_64-linux-gnu/libdl-2.24.so
因此,您的图片是粗略简化。我非常确定VAS的碎片也会发生在其他operating systems上,特别是对于像你的网络浏览器。
答案 2 :(得分:-1)
至少对于Linux和* BSD系统(可能还有其他类似unix的系统),手头的图表是正确的,而我怀疑你在Windows上运行程序显然使用了不同的内存布局。
我还强烈建议不要将代码示例粘贴为屏幕截图。只需将它们直接粘贴并缩进即可。