内存篇之堆泄漏

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

什么是堆泄漏

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

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

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

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

泄漏原因及对策

    所有老师都会强调malloc后一定要有free,但实际编写复杂代码时,内存泄漏几乎不可避免。比如下面多分支退出,某分支忘记释放已分配的内存,就导致泄漏:

    void MyFunc(int size)

    {

      char* p= malloc(size);

      if( !GetStringFrom( p, nSize ) )

      {

        printf(“Error”);

        return;

      }

       …//using the string pointed by p;

      free(p);

    }

    无法完全避免内存泄漏,只能通过一些编程原则减少泄漏的概率:

    1) 减少多分支退出而遗漏free,可用goto语句保证函数只有一个退出点。

    2) 保证在同一层上使用malloc/free对,也就是说不要在子函数中malloc,在外层主函数free。这种内存在不同层次分配释放会使逻辑层次混乱,很容易导致内存泄漏。

    char* AllocStrFromHeap(int len)

    {

      char *pstr;

      if ( len <= 0 ) return NULL;

      return ( char* ) malloc( len );

    }

    相反如果在主函数中malloc并使用内存,而在某子函数中释放参数所指内存,可能导致主函数中出现野指针(后续)。

    3)人工review代码查找内存泄漏很困难,可借助工具快速检测,如boundchecker/pc-lint等都能通过自动扫描代码找到内存泄漏。

隐式泄漏

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值