北斗星君的专栏

NERVE软件开发组

黄庠魁ID:VisionCat
207091次访问,排名326好友0人,关注者18
安静的人
VisionCat的文章
原创 70 篇
翻译 0 篇
转载 4 篇
评论 713 篇
北斗星君的公告
神的话语
歌林多前书13章4-8节
爱是恒久忍耐,又有恩慈。爱是不嫉妒。爱是不自夸。不张狂。不作害羞的事。不求自己的益处。不轻易发怒。不计算人的恶。不喜欢不义。只喜欢真理。凡事包容。凡事相信。凡事盼望。凡事忍耐。爱是永不止息。
ICQ:
206-425-719
MSN:
Huangxiangkui@msn.com
OICQ:
170411742
最近评论
edilyxin:系数变换公式是不是还有一些错误啊?
outskywind:问个小问题,怎么查看在IDE下RUN的结果?
kivia:这个是没办法的,那个记者啊,电视台啊有几个是有基本常识的。
zhongyunde:那怎么使用 OpenWatCOM 编译产生库文件呢 ??
李建国:我安装的时候选择了繁体版的了,可是重新安装就再也没有选择机会了,请指教一下怎么才能恢复啊,谢谢!
文章分类
收藏
    相册
    技术之友
    ShellEx
    链接交换
    在君夜阳的世界
    星之链接
    Chinese Tea
    STUDIO社群
    北斗星君专栏(新)(RSS)
    存档
    软件项目交易
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

    原创 实用小代码之内存泄漏检测(二)收藏

    新一篇: 《荒漠甘泉》4月18日 | 旧一篇: 《荒漠甘泉》4月17日

    实用小代码之内存泄漏检测(二)


        继上次 实用小代码之内存泄漏检测 一文。这次继续介绍另一个我平时用于动态监测内存泄漏的代码。

        我这里所说的 动态监测内存泄漏 是指在程序执行时,以替换 malloc 和 free 函数来达到检测内存泄漏的目的,因为内存泄漏的主要来源就是 malloc 和 free 这组函数。相比那些分析源代码的检测工具,动态监测能够很好的检测循环中分配的内存是否被泄露。下面我不想多说,一切以代码来说话。

        这里的代码只是给各位一个抛砖引玉的借鉴。其中还有很多不完善的地方。比如没有多线程锁之类的问题。

    /*
        PROGRAMER: Wayne Huang
        DATE: 2008.04.18
        LICENCE: GPL v2.0
    */


    #define MMALLOC(s) mm_malloc(s,__FILE__,__LINE__)
    #define MFREE(p) mm_free(p,__FILE__,__LINE__)
    #define MOUTWE "[%s:%d] {%c} 0x%x "

    typedef 
    struct mmbs mmbs;
    struct mmbs{
      mmbs 
    *next;
      
    char *file;
      
    int line;
      
    void *mm;
    }
    ;

    static mmbs mhandle={NULL,0,0,0};
    mmbs 
    *handle=&mhandle;

    void *mm_malloc(unsigned int s,char *file,int line);
    void mm_free(void *p,char *file,int line);
    void mm_exit(int rel);

    void *mm_malloc(unsigned int s,char *file,int line){
      mmbs 
    *p=malloc(sizeof(mmbs)+s);
      mmbs 
    *i=NULL;

      
    if(p){
        p
    ->next=NULL;
        p
    ->file=file;p->line=line;
        p
    ->mm=&p[1];
        
        
    for(i=handle;i->next;i=i->next);

        i
    ->next=p;
      }

      
    return(p->mm);
    }


    void mm_exit(int rel){
      mmbs 
    *t=NULL;

      
    for(t=handle->next;t;t=t->next){
        printf(MOUTWE,t
    ->file,t->line,'E',(int)t->mm);
      }

      
    if(rel){
        t
    =handle->next;
        
    while(t){
          handle
    ->next=t->next;
          free(t);
          t
    =handle->next;
        }

      }

          
      
    return;
    }


    void mm_free(void *p,char *file,int line){
      mmbs 
    *now=handle,*pre=handle;
      
    int nf=1;
      
    if(p){
        
    while(now){
          
    if(now->mm==p){
        pre
    ->next=now->next;
        free(now);
        nf
    =0;
        
    break;
          }
    else{
        pre
    =now;
        now
    =now->next;
          }

        }

        
    if(nf){
          printf(MOUTWE,file,line,
    'W',(int)p);
        }

      }

      
    return;
    }

         用 MMALLOC(size); 替代你原先代码中的 malloc(size); MFREE(p); 替代你原来的 free(p); 然后在程序退出以前 执行函数 mm_exit(1); 就可以查看报告,并将泄漏的内存一并释放。如果需要在代码执行过程中查看内存的分配情况,可以执行 mm_exit(0); 来查看。

        两个函数的不同之处在于,第一个会将未释放的内存释放掉。而第二个只是显示通过函数分配的内存情况。

        对于程序执行过程中的输出 {W} 表示释放了一个没有被申请的内存。而 {E} 表示有内存泄漏的情况。在报告中会指明代码的具体位置等相关信息。


    文外音:
        原本在第一篇文章发表后,我曾记得有个人在我的文章留言里用C++写了一长串的代码,大概是我代码的两倍吧,好像还没贴完。来实现类似于我今天写的这点代码实现的功能,我粗略得看了下。其中用了符号的重载之类的。的确,我没有办法在不改变人们编程习惯的情况下用C语言实现更好的动态监测泄漏的代码。

       我个人的观点是,能用10行代码解决的事情,绝对不要用100行代码来解决。


    北斗星君(黄庠魁)

     

    发表于 @ 2008年04月18日 09:33:00|评论(loading...)|编辑

    新一篇: 《荒漠甘泉》4月18日 | 旧一篇: 《荒漠甘泉》4月17日

    评论

    #热爱大家 发表于2008-04-18 13:01:14  IP: 211.166.227.*
    收下了 谢谢~ ^_^
    #esports52 发表于2008-04-20 13:01:28  IP: 124.72.26.*
    顶了...
    #zju3020912063 发表于2008-04-20 14:49:27  IP: 116.227.123.*
    在不改变人们编程习惯的情况下实现其实非常简单,vc的头文件里就有,
    只要把这个定义放在malloc函数和mm_malloc之后就可以.
    #define malloc(x) mm_malloc((x),__FILE__,__LINE__)
    2008-04-20 18:39:34作者回复
    不得不承认,这样的确可行。但是这样的话,代码会显得比较混乱。因为一般宏名都为大写,这样会引起混淆。<br />所以,我还是不怎么推荐这样使用。
    #bluesky 发表于2008-05-21 19:09:03  IP: 220.231.52.*
    谢谢 感觉很好,有一点没有明白

    void *mm_malloc(unsigned int s,char *file,int line)函数中

    p->mm=&p[1];这句有点不明白
    #bluesky 发表于2008-05-21 19:11:42  IP: 220.231.52.*
    麻烦作者给解释解释阿,为什么新申请的内存地址是p[1]呢
    #北斗星君 发表于2008-05-22 17:06:41  IP: 218.82.173.*
    您好,bluesky
    因为p[0]存放的是内存链的指针,用于指向下一块被分配的内存。
    所以这里是 p[1]。希望我解释的够清楚。
    #temp77 发表于2008-07-14 12:58:38  IP: 203.88.202.*
    记得曾在一个项目当中使用了类似作者的这种内存检测方法(当时在项目经理的指导下),记得老大如是说:能运用在语言级别hack的方法可以提前检测出更多bug的发生(视乎具体语言的语法复杂度,C要比C++容易很多)。
    ` ` ` ` 不过,感觉楼主的提出这个方法太简单了,还不至于能实用阶段。 提出几点建议(无恶意):
    ` ` 1、用链表保存分配过的指针地址是非常慢的操作(遍历链表将是很严重的性能瓶颈,当一秒内有超过千次的内存申请时,恐怕会影响到测试的效果),建议使用更快的hash_table代替;
    ` ` 2、上面zju3020912063 君的说法是对的,尽管宏定义一般都是大写,不过这里用法特殊,建议别拘泥于编程风格(我们项目中对new操作符也作了重载)。
    ` ` 3、加入NDEBUG的宏定义,这样可以使这系列宏只在调试版本中应用,Release版本中自动用回原版的malloc函数。
    ` ` 4、记得要加锁,以适应多线程的运行环境下的可靠运行。
    ` ` 5、为动态获得报告结果,建议把检验的指针地址用信息报的方式(代替printf),jet 到127.0.0.1的一个服务器去(另外写),然后随时随地可以用GUI的方式来呈现内存分配的动态情况(百分比),集中突显问题,甚至可以找出内存分配的峰值在哪里。
    ` ` 6、如果运行在Linux下,考虑与valgrind一起工作,尝试发现更多的内存泄漏问题。
    ` ` 7、额外输出完整的日志(在服务器上),并写一个简单的日志分析小工具协助静态分析内存泄漏状况。

    ` ` ` ` 以上是当时项目进行时的实践经验,效果不错嘀,发现了平常很难发现的内存泄漏,而且由于调试版本与Release版本里内存申请速度相当,并没有引入额外的问题,为加快项目问题收敛率起到决定性的作用!!! (完)
    2008-07-15 09:45:22作者回复
    感谢你的指正。其实我这段代码是消遣的时候随意编写的。所以没有考虑太多的细节因素。纯粹是属于抛砖引玉的目的。<br /><br />我觉得,作为一个说明性的代码,不应该包括太多的内容。主要思想抓住了,接着就是细化的工作。这个细化的工作应该根据不同的人,不同的工作环境有不同的方式。如果一上来就一套非常复杂的示例代码,这样不容易让人快速了解其思想,也不便于别人在实际工作中的应用。<br /><br />在实际应用中,我的代码也应该加入您所说的这几点。
    发表评论  


    登录
    Csdn Blog version 3.1a
    Copyright © 北斗星君