动态分配内存空间 //作者:13*0217

 现实的世界里,我们需要计算一些物理对象(汽车,速度...),但一开始并不能确定它们的数量大小,人类用了抽象的字母符号,替代它们并参与下一步的计算。这一种方法在计算机编程中,个人以为是动态内存分配(Dynamic Memory Allocation),目标不是计算最终结果,而是为一段段代码中的许多“物理对象”获得相应大小的一段内存间。
       程序设计中定义的大多数临时变量(物理对象),由于编译器在编译和链接过程中,会根据变量的类型确定它的内存空间大小,随后,操作系统根据“已知信息”为这些对象直接分配和释放对应大小的空间,其中用到了栈(stack)这种数据结构,比如,一个int类型对象占4个byte空间,这是静态分配内存的方法。它分配的所有空间区域集合,叫做非堆内存区。程序在执行过程中,这些对象被使用过一次后,就不能被再次使用,因为编译器向程序中添加的“维护代码”会释放掉这些空间,同时里面的对象也就被销毁了。那么,在一个函数调用过程结束后,如何还能对相应对象进行多次操作,又可以根据人们的需要来结束它呢?
       操作系统充当了“内存管理者”的角色,划分了一段“自由的内存空间”提供给程序使用,延长了对象的生命周期。它采用了一种叫做堆(heap)的数据结构,里面存放的是内存中不连续的地址,意味着很多对象在内存里是零散存的。
我把这段自由的内存空间称之为堆内存区。要想使用堆内存区来存储“特殊要求”的对象,不同的语言向操作系统申请方式会不一样。C语言中提供了malloc和free函数来人为地开始和结束堆内存区的使用。例如:
       a)  char *File = (char *)malloc(sizeof(char))  
       b)  free(File)
       a中表明:使用字符指针*File指向了堆内存区中的对象,分配的大小是sizeof(char), 在不需要的时候用b中的free函数来释放空间。进一步的讲,操作系统在此过程中做了4件事情。首先,操作系统遍历堆中的所有结点,根据“情报”找出第一个“满足条件”的结点,删除结点并把此空间用来存储对象。其次,添加“额外的代码”,维护运行期间每个对象的使用。再次,操作系统把多余的空间,重新放入空闲的堆中。最后,操作系统提供了对象大小信息,用free函数就能正确的释放空间了。
       用堆获得的内存空间灵活,比较大,受限于计算机系统的有效虚拟内存空间。但其缺点也比较明显。
       一旦忘记了使用free函数销毁对象,那么在运行期间,操作系统就无法为其他应用程序对象自由分配这段空间,情况越糟糕的话,计算机的整体运行速度就会变慢,甚至死机。直到程序结束后,操作系统才会回收这个堆内存空间。
       基本了解了堆内存区后,就可以利用它在计算机中组织大量的数据(对象),一般采用链表这种数据结构来高效实现。通过动态内存分配,这些有组织的数据都放在了堆内存区中,节省了存储空间,方便了程序的实用,其重要性可想而知。清晰的认识堆内存区作用与意义,是学习数据结构的理论基础之一,个人认为。

【一些疑惑】
       内存里不同的程序区,都是按照从低地址到高地址方向扩展么?又是怎样的一个分配情况呢?从整个内存的角度看,它们有先后顺序么?

【参考文章】
1、栈空间和堆空间    http://blog.163.com/hangqiang321@yeah/blog/static/164202800201181453113213/
2、浅析栈区和堆区内存分配的区别    http://bubuko.com/infodetail-731164.html

【延伸阅读】
1、简析堆内存 http://blog.csdn.net/dongpy/article/details/4555875
2、堆 http://www.cnblogs.com/vamei/archive/2013/03/20/2966612.html
3、Linux操作系统内存分配方法总结 http://soft.chinabyte.com/os/392/12625892.shtml
4、从内存的角度观察堆、栈、全局区、文字常量区、程序代码区 http://www.cnblogs.com/huhuuu/p/3440187.html

posted on 2015-05-14 00:30  call_from_dream  阅读(220)  评论(0编辑  收藏  举报

导航