IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    内存泄漏

    Yukang (moorekang@gmail.com)发表于 2010-12-22 00:00:00
    love 0
    以前写的一些程序运行一段时间后占用的内存越来越多,估计是内存泄露了。服务端的程序要长时间的运行,内存泄露是个很严重的问题。于是再检查程序,很崩溃的是还有另外一个模块不是自己写的,看起来很麻烦。看了半小时后发现一些问题,但是还是不能保证是否完全解决了。同事让我用以前他们写的一些函数,对应的为MALLOC和FREE。仔细看了一下觉得很不错,其实就是把malloc和free函数封装了一下,用来记录申请空间的文件和代码位置,使用方法就是用MALLOC和FREE替代原来的函数。主要的数据结构是:
    typedef struct
    {
    	long pcode;                          //指针
    	char filename[128];                  //申请空间的源文件名称
    	int line;              //申请空间的代码所在的行
    	int ct;				   //内存状态: 0-未闭合,1-闭合,2-log/脚手架
    }mem_info;
    
    mem_info mem_in[MEM_SIZE];  //MEM_SIZE最大指针数目
    int mem_in_id; //数组中已经占有的mem_info数目
    int mem_check_statue; //是否进行内存泄露检查
    然后有两个函数,一个是初始化函数mem_check_init(),另一个为mem_check_write(),这样就能检查者两个函数之间的代码是否有内存泄露,mem_check_write()可以打印成一个表,所有申请了空间的代码的文件名称和代码所在的行数,以及运行到mem_check_write()这里的时候所有申请空间的状态,1表示已经释放,0表示申请未释放,2表示的是脚手架的位置(用来方便检查哪一小段代码是否有内存泄露)。
    #define MALLOC(size)  __ck_malloc(size,__FILE__,__LINE__) //__FILE__ 文件 __LINE__ 代码所在行
    void   *__ck_malloc(int size,char *file,int line)
    {
    	void *p=malloc(size); 
    
    	if (mem_check_statue)	return p;
    	if (mem_in_id>=MEM_SIZE) return p;
    
    	mem_in[mem_in_id].pcode=(long)p;
    	strcpy(mem_in[mem_in_id].filename,file);
    	mem_in[mem_in_id].line=line;
    	mem_in[mem_in_id].ct=0; // 状态: 0-未闭合
    	mem_in_id++;
    
    	return p;
    }
    那么FREE(p),进行的操作就是现在数组中找到是否有这个p,如果有就改变状态,变为1表示闭合了,也就是释放掉了。CALLOC和MALLOC类似,是调用calloc,函数malloc()和函数calloc()的主要区别是前者不能初始化所分配的内存空间,而后者能。REALLOC有点不一样,调用void* np=realloc(p,size),这里要注意np和原来的p有可能不一样,有可能一样,比较一下进行相应处理。最后mem_check_write()遍历上上面的数组打印出来表,其顺序就是按照代码执行的顺序了,其中脚手架可以比较方便的定位于申请了没有释放的代码行,也就是查找两个2之间的0所对应的行。 这是一个很不错的方法,今天用这个办法找到了好多处不易发现的内存泄露错误。但这也有其缺点,即使完全通过也不能保证就完全没内存泄露了,除非测试时运行代码的覆盖率要保证所有代码都运行到了,这也是正规的、高质量的测试所要做到的程度。我们现在没有时间来做足够好的测试,以后再好好规范一下。


沪ICP备19023445号-2号
友情链接