分类:
2012-10-13 14:04:30
c语言程序所使用的内存总体可以分成两类,静态存储区和动态存储区。静态存储区包括:只读数据区 rodata,已初使化的读写数据区rwdata,未初始化读写数据区bss。动态存储区包括堆内存区域和栈内存区域。
静态存储区在程序运行中是不会变化的,其大小位置在程序运行过程中都是固定的,只有当程序退出时,静态存储区才会被系统收回。
动态存储区都是在程序运行过程中动态分配的,大小在程序运行的过程中动态变化。
动态内存管理形式:栈内存从高地址向低地址分配,堆内存将从低地址向高地址分配。
动态内存管理实现角度:堆使用链表来实现,栈使用线性存储的方式。
低地址
只读数据区 |
已经初始化读写数据区 |
未初始化读写数据区 |
堆内存 |
|
栈内存 |
堆内存的分方式是非连续的方式,而栈内存的增长方向是连续的方式。
栈内存由编译器管理的,而堆内存是由程序调用具体库函数管理的。
栈内存的使用在很大程度上依赖于处理器硬件机制,在处理器中,一般有一个寄存器来表示当前栈指针的位置,通常在内存中分配一块区域,这块内存的上界与下界之间是可用的栈内存区域。
栈内存的两种增长方式:一种是向上增长,即从低地址向高址增长,另一种向下增长,即从高地址向低地址增长。
注意:栈内存可能使用满栈与空栈两种情况,在满栈的情况下,栈指针当前的位置是已经使的区域;在空栈的情况下,栈指针当前的位置是没有使用的栈区域。
堆内存
堆内存的分配过程中,每次分配将返回一个当前分配地址的指针。在程序中如果多次分配,可得到多个内存指针。每个内存指针都分配内存地址。在释放内存时,只要对每个指针操作,那个指针所指向的内存就会被释放,而对其它内存区域没有影响。
从分配与使用上,栈内存与堆内存的区别:栈只有一个入口,就是栈指针,栈指针标识当前栈区域中已经使用与未使用的界限,程序访问栈内存的时候都只能通过栈指针及其偏移量,而堆内存有多个入口,每次分配得到的指针是访问内存的入口,每个分配内存都可被单独释放。
堆内存整体分配方向是逐渐向高地址分配,这只是一个大体的增长方向。在堆内存中,已经使用的区域与未使用的区域是交错的,像栈区域那样有明显的分界线。
堆与栈内存管理的区别
堆与栈都是c语言中的动态内存,在内存管理方向,栈内存由编译器管理,而堆内存由程序调用c语言的基本库函数管理。
在分配的方面,栈内存分配的时候,编译器将利用处理器硬件的栈指针机制,分配的速度是很快的,在释放的时候也只需要移动栈指针的位置。而堆内存需要通过库数使用较为复杂的算法来分配,其中还要从系统中寻找可以分配的内存。
在错误处理方面,堆内存在分配的时候,可以在程序中判断malloc()等函数的返回值是否为null来确定对内存是否分配成功,是否可以使用。而栈内存在分配的时候,不能在程序中判断其成功与否,当栈内存的使用量比较大的时候(例如使用函数进行递归运算),栈内存可能超出系统的容量,这时程序运行将发生栈溢出错误。
在使用的方面,栈内存不需要程序来管理,同时,函数内部的栈内存是不能被函数的调用者使用的。堆内存需要在程序中处理它的分配与释放情况,可以利用灵活的程序将堆内存的指针从函数的内部传递到函数的外部,这时各个函数都可以使用别的函数分配出来的堆内存。
在一个函数中使用malloc()等函数分配内存,利用参数和返回值将内存指针传递给其他函数,然后在其他的函数中使用和释放这块内存都是可以的。
在c语言语法的方面对栈内存和堆内存如何使用没有限制。然而从使用的角度,栈内存更适用于容量较小的变量(例如:c语言的基本变量类型、较小的结构体和数组),堆内存则适用于开辟较大块的内存。
一些问题的回答:
参考来源: