编译后文件的结构
加载
程序的内存布局
注意,这是说的进程,要和可重定向文件和可执行文件的结构分开。
linux x86-64 中,代码段总是从地址 0x400000
开始,
- bss 段 (bss segment) 通常是指用来存放程序中未初始化的全局变量的一块内存区域。
- 数据段 (data segment) 通常是指用来存放程序中已初始化的全局变量的一块内存区域。
- 代码区:存放函数体二进制代码,由操作系统进行管理的。这部分是共享的而且是只读的。
- 栈区:由编译器自动分配释放,函数的参数值,局部变量。栈帧
- 堆区:程序员分配和释放,若不释放,程序结束时由操作系统回收
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
High Addresses ---> .----------------------.
| | Kernel space, 1GB for Linux,
| Environment | 2GB for Windows by default.
2^48-1 -> |----------------------|
| | Functions and variable are declared
| STACK | on the stack.
base pointer -> | - - - - - - - - - - -|
| | |
| v |
| |
| | The stack grows down into unused space
| Empty | while the heap grows up.
| |
| ^ |
| | |
| - - - - - - - - - - -|
| other memory maps | Other memory maps do occur here, such
| | as dynamic libraries, and different memory
| | allocate)
|----------------------|
| |
| |
| |
| ^ |
| | |
brk point -> | - - - - - - - - - - -| Dynamic memory is declared on the heap
| HEAP |
| |
|----------------------|
| BSS | Uninitialized data (BSS)
|----------------------|
| Data | Initialized data (DS)
|----------------------|
| Text | Binary code
0x400000 ----> |----------------------|
| |
Low Addresses ----> '----------------------'
动态存储区
其中栈区和堆区是动态存储区。
栈区
- 栈区是连续的内存区域,大小是固定的,生长方向从高到低,能从栈上获得的空间较小,操作系统底层对栈这种数据结构提供了支持,因此速度很快,且不会有碎片。Linux 默认是 8M 左右,可以调整。
- 栈是线程独有的,保存其运行状态和局部自动变量的。栈在线程开始的时候初始化,每个线程的栈互相独立,因此,栈是 thread safe 的。每个 C++对象的数据成员也存在在栈中,每个函数都有自己的栈,栈被用来在函数之间传递参数。操作系统在切换线程的时候会自动的切换栈,就是切换 SS/ESP 寄存器。
- SP(栈指针)寄存器跟踪栈的顶部。
堆区
- 堆区是不连续的,系统采用空闲链表的方式来管理空闲内存的地址,堆的大小受限于操作系统的大小。频繁的 new/delete 会造成大量碎片,使程序效率降低。
- 堆是属于进程的。 TODO: brk, sbrk
静态存储区
内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。它主要存放静态数据、全局数据和常量。
BSS 段
历史原因,在汇编中曾有 block started by symbol
. 程序开始执行前,内核将此段中的数据初始化为0或者空指针。
Data 段
.data
已初始化的全局和静态变量。
代码区
.text
已经编译好的机器代码。这个段是只读的,并且是可共享的,也就是多个进程可以共享一个代码副本以节省内存。