Unix中C程序内存布局
C程序在进程中分为代码片段(text segment)、初始化数据片段(initialized data segment)、未初始化数据片段(uninitialized data segment)、栈(stack)以及堆(heap)。其内存分布如图1所示
图1. C程序运行时内存布局
- 代码片段往往是只读内容,为进程运行提供必要的操作步骤。
- 初始化数据片段包含C代码中明确初始化了的变量值。
- 未初始化数据片段(又称为bss段),包含C代码中未明确初始化的变量,该片段中数据在程序启动时被全部重置为0(按位全部填充为0)。
- 栈用于存储程序运行时的自动局部变量(automatic variables)、函数调用信息等。由于函数调用栈中表现为向低地址增长函数链,当出现递归调用时,函数链被拉长,自动局部变量被存储为一个新的变量,因此,递归调用从内存分布上来说产生了一个新的函数,函数中的变量不会相互干扰。
- 堆用于存储在程序运行时动态申请内存空间的变量。
ISO C标准中有三种方式可以动态申请内存空间(在堆中):
- 调用malloc函数,指明申请空间大小。申请后将不进行初始化操作,因此使用malloc函数申请到的内存片段中值为未知量。
- 调用calloc函数,指明申请单元大小及申请单元个数。申请后将对该内存片段按位形式赋0。
- 调用realloc函数,扩大或缩小已动态申请过的内存片段大小。
当不再使用该内存片段时,需要使用free函数对该内存片段予以释放,以免造成内存泄,降低程序性能。其函数原型为
#include <stdlib.h> void *malloc( size_t size ); void *calloc( size_t nobj, size_t size ); void *realloc( void *ptr, size_t newsize ); void free( void *ptr );
使用realloc函数增加内存片段时,如果没有适当的空闲内存片段与之相邻,系统会将申请一个新内存片段,并把原有内存片段中的数据复制到新片段中,将原有内存片段释放,返回新地址。如果原有内存片段地址呗其他变量保存,并在realloc调用后使用,将引起内存调用错误(内存地址被改变)。