C语言内存分配

网上看到一 篇讲得不错的关于内存分配的文章,对其中的知识进行了归纳整理和验证,也算是解决了困惑已久的疑惑了,如有理解不当之处,希望多多指正。

原文:http://blog.csdn.net/youoran/article/details/10990815#comments

内存布局

在认识内存分配之前,我们需要先了解一个可执行程序在运行前内存上对应的数据分区

yuanhui@C179:~/c$ sizea.out

   text   data     bss     dec    hex filename

   1448    576       8    2032    7f0 a.out

代码区静态数据/全局初始化数据区 未初始化数据区 十进制总和 十六进制总和 文件名

1、  代码区的指令包括操作码和需要操作的对象,该区域的数据一般是只读的,

2、  数据区是一些初始化的全局变量、静态变量、常量

3、  未初始化数据区(bbs)是一些未初始化的全局变量,该区域的值在函数程序执行之前被赋值为0或者是空指针,在运行时改变其值。

当程序运行的时候对应的就产生了堆区和栈区。


栈区:由编译器自动分配释放,存放函数的参数值、局部变量的值等

堆区:用于动态内存分配。堆在内存中位于bss区和栈区之间。一般由程序员分配和释放,若程序员不释放,程序结束时有可能由OS回收

下面的例子讲述了数据的内存上的布局


内存分配

静态分配和动态分配,

1、静态分配是在程序执行之前就分配了的,所以相对而言,他的效率是比较高的

2、静态分配是有名字的变量,而动态分配则需要使用指针间接地对它进行操作。

Int a= 100:编译器分配存储区来存放这个整数,该存储区和名称a相互对应,并用100初始化这个存储区

p=(int*)malloc(sizeof(int))在堆区分配4个字节的存储区,返回该存储区的地址,并初始化给指向整形类型的指针p,如果需要访问存储区的数据,需要通过访问他的地址来访问这个对象

3、静态对象的分配和释放由编译器自动完成,动态对象的分配和释放必须由程序员自己管理。

堆和栈的区别

1、管理方式

栈是直接由编译器管理的,堆是由程序员自己管理的

2、空间大小不同

栈是向低地址扩展的数据结构,栈顶地址和栈的大小是预先设定好的,而且他的地址空间是连续的,所以容量一般较小

堆是向高地址扩展的数据结构,他的地址不是连续的,因为只要是高地址上有剩余的空间他就可以不停的开始动态分配,来使用一些相对来说比较零散的地址空间,为什么我们在使用指针的时候一定会遇到链表这个东西呢!因为堆上的空闲的内存地址就是使用链表来存储的。这样堆的数据也比较大。

3、存储数据

栈:函数的参数、需要多次调用的代码(递归)、局部变量

堆:动态分配的地址

4、是否产生碎片

对于堆来说,频繁的malloc和free一定会产生磁盘空间不连续,从而产生很多的碎片,程序在退出的时候(会对磁盘空间进行回收管理)但是太多的磁盘碎片会使得程序效率降低。

5、增长方向不同

堆上的地址是向上增长的,栈上的地址是向下增长的。

6、分配方式不同

堆上空间是动态分配,栈上的空间是静态分配

7、分配效率

栈的分配效率高于堆:栈是由编译器直接管理的,计算机底层会直接对栈提供支持,堆

则需要调用库函数,他的分配机制很复杂,库函数会按照一定的算法在地址空间是搜索可用的足够大的空间,如果没有足够大的可用操作空间,就需要操作系统来重新整理内容空间,然后再开始分配

C内存分配函数

在栈上分配内存的函数是calloc,实际上还有一个对malloc进行简化和优化的函数叫alloca函数,这个函数对分配的内存空间再进行了一次初始化设置对他的空间进行初始化,这也是以前敲代码的时候没有注意到的地方,malloc函数是没有自带初始化的功能的,所以我们需要使用memset进行初始化

所有的内存分配函数,都是在堆上分配一个连续的空间,产生碎片化是指整个堆上的磁盘文件会产生碎片,但是内存分配函数分配的空间是一个连续的空间。

所以会存在分配内存空间失败的情况,这个时候,我们就需要对分配完成的内存空间做相应的判断。


 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值