C语言内存分布(Memory Layout)#

在富操作系统中(比如Linux)C语言编译后的二进制文件中只包含有代码段、已初始化数据段和一些其他的描述信息(比如BSS段的大小)。BSS段和堆栈是由C库和操作系统初始化的。

C运行时内存布局:

test_uml

.text 代码段 .data 已初始化数据段(RW),保存的是已经初始化的(非0)全局变量和局部静态变量 .bss(Block Started by Symbol) 未初始化数据段(RW),保存的是未初始化的(值为0)的全局变量和局部静态变量。 .rodata 只读数据段,保存的是只读变量,比如const修饰的变量和常量字符串

.comment 注释信息段 .note.GNU-stack 堆栈提示段

生成map文件

gcc -Xlinker -Map=output.map test.c

gcc -o test test.c -Wl,-Map,test.map
gcc test.c -Wl,-verbose
/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) (.gnu.lto_) }
DISCARD关键字用于将指定段舍弃,不出现在输出文件中.

1. 静态区域#

1.1. Text#

包括代码段(code)和只读数据段(RO)

1.2. 已初始化数据段(RW data)#

1.3. 未初始化数据段(BSS)#

2. 动态区域#

2.1. 栈#

栈内存只在程序运行时出现,在函数内部使用的变量、函数的参数以及返回值将使用栈空间,栈空间由编译器自动分配和释放。其操作方式类似于数据结构中的栈。

2.2. 堆#

堆内存只在程序运行时出现,一般由程序员分配和释放。在具有操作系统的情况下,如果程序没有释放,操作系统可能在程序(例如一个进程)结束后回收内存。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。

3. 可执行程序的状态#

  • 一个可执行程序分为镜像和运行时两种状态
  • 镜像文件中包含代码段、只读数据段、读写数据段
  • 在程序运行之前加载的过程中,将动态生成未初始化数据段(BSS),在程序运行时将动态生成堆(Heap)和栈(Stack)区域