关于内存布局的认知

在没有运行程序前,或者说程序未加载到内存前,可执行程序内部已经分好3段信息,分别为代码段text/code,数据段data,未初始化数据段bss3 个部分.

程序在加载到内存前, code segment,data,bss的大小就是固定的.当运行可执行程序,系统把程序加载到内存后,除了根据可执行程序的信息分出代码段,数据段和未初始化数据段之外,还额外增加了栈区与堆区.

代码段(code segment)

代码段存放 CPU 执行的机器指令.通常代码段是可共享的(即另外的执行程序可以调用它),使其可共享的目的是对于频繁被执行的程序,只需要在内存中有一份代码即可.

代码段通常是只读的(如x86/Arm体系),使其只读的原因是防止程序意外地修改了它的指令.但特定的体系结构允许自修改代码段(如IBM/360型号可以实现Self-modifying code).

代码段一般放在堆或堆栈的下面,以防止堆和栈溢出覆盖到它.

数据段(data segment)

此段含了程序中已初始化的全局变量,静态变量(包括全局静态变量和局部静态变量)和常量数据,它有的部分是只读,有的部分是可读可写.

所有已初始化且含有const修饰的数据通常是在.rodata段(也可能是code segment).

在程序运行后,其生存周期为整个程序运行过程.

未初始化数据段(bss segment)

bss存入的是全局未初始化变量和未初始化静态变量,未初始化数据区的数据在程序开始执行之前被内核初始化为0或者空NULL,其生存周期为整个程序运行过程.

栈区(stack segment)

栈是一种先进后出的内存结构.由编译器自动分配释放,存放函数的参数值/返回值/局部变量等.在程序运行过程中实时加载和释放,因此,局部变量的生存周期为申请到释放该段栈空间.

堆区(heap segment)

堆是一个大容器,它的容量要远远大于栈,但没有栈那样先进后出的顺序.

堆用于动态内存分配.堆在内存中介于BSS区和栈区之间.一般由程序员分配和释放.若程序员不释放,程序结束时由操作系统回收.