内存分区
# 内存分区
可执行文件被加载时,系统会给程序分配内存空间,程序的代码指令和数据在内存空间中都有自己的区域。
可执行文件的组成:
- 代码段:
.text段
:存放的是可执行文件的可执行指令。.rodata段
:存储常量和字符串常量。
- 数据段:
.bss段
:存放未初始化
的全局变量和 static 变量。并不占二进制大小,只是为未初始化的全局变量和局部静态变量预留位置。.data段
:初始化
的全局变量、static 变量。
当可执行文件被加载到内存后,程序在内存中的五大分区如下:
代码区
:代码指令存放的区域,只读。常量区
:存放常量的区域。静态(全局)区
:静态变量和全局变量存放的位置。初始化的变量在一块区域,未初始化的在另一个区域。在程序结束时由系统回收。堆区
:动态申请的内存区。在程序运行过程中,由程序员负责管理回收,程序结束时由系统回收。栈区
:系统分配。主要存放临时变量和函数入参,用于维护函数调用的上下文。默认情况下:Linux 默认8M
,Window 默认1M
。
代码区
,常量区
,静态(全局)区
在编译期分配好了内存空间并初始化。
Linux 下进程在内存中的经典布局如下:
程序运行在系统的内存空间里,这些空间一部分给系统内核使用,这部分我们称之为内核空间
,剩余部分就是用户空间
。
Windows 在默认的情况下会将高地址的 2GB 空间分配给内核(也可以配置 1GB)。
Linux 默认情况下将高地址的 1GB 空间分配给内核。
1
2
2
stack
: 栈用于维护函数调用的上下文,离开了栈,函数调用就无法实现,栈通常在用户空间的最高地址处分配。heap
:堆是用来容纳应用程序动态分配的内存区域,当程序使用 malloc 或者 new 分配内存的时候,得到的内存会来自堆里。堆通常存在栈的下方(低地址方向),在某些时候,堆也可能没有固定统一的存储区域。堆一般比栈大很多,可以有几十至数百兆字节的容量。dynamic libraries
: 这个区域用于映射装载的动态链接库。在 Linux 下,如果可执行文件依赖其它共享库,那么系统就会为它在从 0x40000000 开始的地址分配相应的空间,并将共享库载入该空间。read/write sections
,readyonly sections
:可执行文件映像。 存储着可执行文件在内存里的映像,由装载器在装载时将可执行文件的内存读取或映射到这里。reserved
:保留区并不是一个单一的内存区域,而是对内存中受到保护而禁止访问的内存区域的总称:例如大多数操作系统中,极小的地址通常都是不允许访问的,如 NULL,C 语言将无效指针赋值为 0 也是这个考虑。
上次更新: 2022/06/17, 07:22:19