【转】c内存泄漏问题

c语言的内存泄漏问题

(2016-02-14 09:52:06)
  


堆泄漏

堆泄漏即常说的内存泄漏,是嵌入式软件里的常见问题,会导致软件运行一段时间后内存耗尽。

什么是堆泄漏

    内存分配和释放的操作是程序员根据需要动态随机发起,程序本身(或编译工具)无法自动判断某块已分配的内存什么时候不再被使用,必须由程序员自己手动调用free释放,以便为其他程序腾出空间。而一旦程序员忘记释放某块内存,它就不能回到可用内存,系统总的可分配内存就随之减少,这就是内存泄漏。注意这里的内存特指堆(heap),只有堆内存才需要程序员自己控制分配和释放。所以内存泄漏和堆泄漏是同一概念。

    新手对泄漏这个词往往感到不理解,不就是分配后忘记释放,怎么叫泄漏呢?叫内存丢失不是更通俗么?

    关于这点,可以打个比方,分配内存就是从银行贷款,而释放内存就是给银行还钱。如果有人借了钱却赖帐不还,那么银行可支配的钱就会减少,银行总资产就被损失或泄漏。类似,堆是一块固定大小内存,“借”给不同程序使用,如果某个程序只借不还,堆管理所能支配的内存就减少,因此内存泄漏是针对系统中总的可支配内存资源来说,而并不是物理内存真的丢失。从这个角度理解,leak绝对比lost更准确生动:一种资源在封闭系统中循环使用,如果部分资源无法回到循环,不正是泄漏到封闭系统之外了么

   借钱不还的银行客户越来越多,最终银行就会因为没钱放贷周转而破产。同样发生内存泄漏,直接的表现就是软件运行越来越慢,最终甚至因分不到内存而崩溃。(所以说一定要判断malloc的返回值,不是每次都能从银行借到钱滴)



隐式泄漏

    是指某内存已使用完,明明可以早点free掉,却非等到软件退出前才释放,俗称“占着XXXX”,虽然程序最终释放了所有内存,严格意义上没有泄漏,但某些场合隐式泄露同样会导致严重后果:比如某长期运行的服务器程序,如果不断分配而不及时释放内存,最后系统很可能在运行中途就因堆内存耗尽而crash,因此内存使用过程中,不但要确保释放内存,而且用完要尽快释放,而不要全等到退出前释放,以消除隐式泄漏,确保内存占用峰值不超过系统堆资源上限。



我们先从一个函数来分析内存泄漏的原因:

char *doSomething()

{

     char *p;

     char *q;

     if( ( p=malloc( 1024 )  ) ==NULL ) returnNULL;

     if( ( q=malloc(2000 )  ) ==NULL ) return NULL;

    .......

     returnp;

}

分析一下这个函数,我们会发现开发人员考虑了p和q内存分配失败的问题,但是却考虑不周,加入,p内存分配成功,而q内存分配失败,那么returnNULL后,p指向的1024个单元的内存就丢失了,造成了内存泄漏。

      造成内存泄漏的原因一般有以下几种原因:

1、开发人员动态申请内存后,忘记了释放内存

2、多个开发人员在合作开发的过程中,由于沟通不足,没有明确的规定由谁来申请内存,有谁来释放内存

3、free()函数是根据malloc()申请的内存控制信息来释放内存的,换句话说,free只能释放由malloc函数返回的内存指针,而在这期间,如果malloc分配的内存,其指针发生了变化,free函数将不能释放该内存,从而造成内存泄漏。关于这一点可以举个例子:

void doSomething( char *ptr )

{

        char *p;

        int i;

         if( ptr == NULL )  return; // 入口参数合法性检查

         if(( p= (char *) malloc ( 1024 ) ) ==NULL ) return; //分配空间并检查

        for( i=0; i< 1024; i++ )

        {

                  *p++ = *ptr++;

        }

        ......

        free( p );

         return;

}

这个函数考虑了动态申请内存,以及释放内存,但是忽略了一点,就是在释放前p的值已经发生了改变,所以free(p)函数执行失败。因此仍然会造成内存泄漏。要应对这种问题,就是要保存p指针,例如可以采用如下方式:

 * ( p+i) = *(ptr+i)   ;       或者 *( p + i)= *ptr++;

这样就回避了以上问题。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值