北斗星君的专栏

NERVE软件开发组

用户操作
[即时聊天] [发私信] [加为好友]
北斗星君ID:VisionCat
211701次访问,排名333好友0人,关注者19
安静的人
VisionCat的文章
原创 70 篇
翻译 0 篇
转载 4 篇
评论 713 篇
北斗星君的公告
神的话语
歌林多前书13章4-8节
爱是恒久忍耐,又有恩慈。爱是不嫉妒。爱是不自夸。不张狂。不作害羞的事。不求自己的益处。不轻易发怒。不计算人的恶。不喜欢不义。只喜欢真理。凡事包容。凡事相信。凡事盼望。凡事忍耐。爱是永不止息。
ICQ:
206-425-719
MSN:
Huangxiangkui@msn.com
OICQ:
170411742
最近评论
shellex:在Linux下写C#...哎,虽然有Mono
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 © 北斗星君