免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 9729 | 回复: 19
打印 上一主题 下一主题

内存泄露检测的一个怪问题(采用memwatch) [复制链接]

论坛徽章:
24
15-16赛季CBA联赛之北京
日期:2018-08-17 18:43:33技术图书徽章
日期:2018-08-22 12:53:57技术图书徽章
日期:2018-08-22 12:54:20技术图书徽章
日期:2018-08-22 12:54:3015-16赛季CBA联赛之福建
日期:2018-10-19 16:58:1619周年集字徽章-庆
日期:2019-08-27 13:28:5619周年集字徽章-19
日期:2019-08-27 13:31:2619周年集字徽章-19
日期:2019-08-27 13:31:2615-16赛季CBA联赛之同曦
日期:2019-09-05 12:03:2819周年集字徽章-周
日期:2019-09-06 18:54:5415-16赛季CBA联赛之上海
日期:2018-07-25 11:55:2615-16赛季CBA联赛之青岛
日期:2018-07-10 14:13:18
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-09-14 16:01 |只看该作者 |倒序浏览
我写了个程序,进行内存测试,  
发现如果我把存在内存泄露函数放在同一个.C文件里进行编译时, 是可以检测到的,
但是如果我把这个函数放到别的文件(.H 或.C文件里), 采用包含该文件的形式进行编译测试时,就检测不到.
大家看看这是怎么回事呢?

[ 本帖最后由 incle 于 2007-9-14 16:21 编辑 ]

论坛徽章:
24
15-16赛季CBA联赛之北京
日期:2018-08-17 18:43:33技术图书徽章
日期:2018-08-22 12:53:57技术图书徽章
日期:2018-08-22 12:54:20技术图书徽章
日期:2018-08-22 12:54:3015-16赛季CBA联赛之福建
日期:2018-10-19 16:58:1619周年集字徽章-庆
日期:2019-08-27 13:28:5619周年集字徽章-19
日期:2019-08-27 13:31:2619周年集字徽章-19
日期:2019-08-27 13:31:2615-16赛季CBA联赛之同曦
日期:2019-09-05 12:03:2819周年集字徽章-周
日期:2019-09-06 18:54:5415-16赛季CBA联赛之上海
日期:2018-07-25 11:55:2615-16赛季CBA联赛之青岛
日期:2018-07-10 14:13:18
2 [报告]
发表于 2007-09-14 16:07 |只看该作者
程序这把 mem_alloc()函数放在这儿就可以顺利检测得到内存泄露.  

gcc -DMEMWATCH -DMW_STDIO -I../include -o incle_mem incle_mem.c memwatch.c


  1. #include <stdlib.h>
  2. #include <unistd.h>
  3. #include <sys/types.h>
  4. #include <sys/stat.h>
  5. #include <stdio.h>
  6. /* #include "incle.h"  */
  7. #include "memwatch.h"


  8. char testfile[256] = "";
  9. char work_space[1024] = "";

  10. int mem_alloc(void)
  11. {
  12.         char *ptr1;
  13.         char *ptr2;

  14.         printf(" Memory malloc... \n");
  15.         if( (ptr1 = malloc(512)) == NULL )
  16.                 return 1;
  17.         if( (ptr2 = malloc(512)) == NULL )
  18.                 return 1;
  19.         ptr2 = ptr1;

  20.         printf("\n\n .... free ....\n");
  21.         free(ptr2);
  22.         free(ptr1);
  23.         return 0;
  24. }

  25. int main(void)
  26. {
  27.     /* Init works */
  28.         sprintf(work_space, "/tmp/incle-testDIR-%d", getpid());
  29.         if (mkdir(work_space, S_IRWXU) != 0) {
  30.                 perror("Create work space error");
  31.                 exit(1);
  32.         }
  33.         chdir(work_space);
  34.         printf(" Debug Memory leak\n");
  35.         mwInit();
  36.         mem_alloc();
  37.         if (mwFini() != 0) {
  38.                 printf("memwatch report error on %s/memwatch.log\n", work_space);
  39.                 exit (98);
  40.         }
  41.         return 0;
  42. }

复制代码

[ 本帖最后由 incle 于 2007-9-14 16:09 编辑 ]

论坛徽章:
24
15-16赛季CBA联赛之北京
日期:2018-08-17 18:43:33技术图书徽章
日期:2018-08-22 12:53:57技术图书徽章
日期:2018-08-22 12:54:20技术图书徽章
日期:2018-08-22 12:54:3015-16赛季CBA联赛之福建
日期:2018-10-19 16:58:1619周年集字徽章-庆
日期:2019-08-27 13:28:5619周年集字徽章-19
日期:2019-08-27 13:31:2619周年集字徽章-19
日期:2019-08-27 13:31:2615-16赛季CBA联赛之同曦
日期:2019-09-05 12:03:2819周年集字徽章-周
日期:2019-09-06 18:54:5415-16赛季CBA联赛之上海
日期:2018-07-25 11:55:2615-16赛季CBA联赛之青岛
日期:2018-07-10 14:13:18
3 [报告]
发表于 2007-09-14 16:16 |只看该作者
如果我把 mem_alloc() 放在另一个文件里面( incle.h)


  1. #include <stdlib.h>

  2. int mem_alloc(void)
  3. {
  4.         char *ptr1;
  5.         char *ptr2;

  6.         printf(" Memory malloc \n");
  7.         if( (ptr1 = malloc(512)) == NULL )
  8.                 return 1;
  9.         if( (ptr2 = malloc(512)) == NULL )
  10.                 return 1;
  11.         ptr2 = ptr1;

  12.         printf("\n\n .... free ....\n");
  13.         free(ptr2);
  14.         free(ptr1);
  15.         return 0;
  16. }
复制代码


然后主文件调用这个函数,这样就没法检测试得到内存泄露.



  1. #include <stdlib.h>
  2. #include <unistd.h>
  3. #include <sys/types.h>
  4. #include <sys/stat.h>
  5. #include <stdio.h>
  6. #include "incle.h"
  7. #include "memwatch.h"

  8. char testfile[256] = "";
  9. char work_space[1024] = "";

  10. int main(void)
  11. {
  12.     /* Init works */
  13.         sprintf(work_space, "/tmp/incle-testDIR-%d", getpid());
  14.         if (mkdir(work_space, S_IRWXU) != 0) {
  15.                 perror("Create work space error");
  16.                 exit(1);
  17.         }
  18.         chdir(work_space);
  19.         printf(" Debug Memory leak\n");
  20.         mwInit();
  21.         mem_alloc();
  22.         if (mwFini() != 0) {
  23.                 printf("memwatch report error on %s/memwatch.log\n", work_space);
  24.                 exit (98);
  25.         }
  26.         return 0;
  27. }
复制代码

[ 本帖最后由 incle 于 2007-9-14 16:23 编辑 ]

论坛徽章:
24
15-16赛季CBA联赛之北京
日期:2018-08-17 18:43:33技术图书徽章
日期:2018-08-22 12:53:57技术图书徽章
日期:2018-08-22 12:54:20技术图书徽章
日期:2018-08-22 12:54:3015-16赛季CBA联赛之福建
日期:2018-10-19 16:58:1619周年集字徽章-庆
日期:2019-08-27 13:28:5619周年集字徽章-19
日期:2019-08-27 13:31:2619周年集字徽章-19
日期:2019-08-27 13:31:2615-16赛季CBA联赛之同曦
日期:2019-09-05 12:03:2819周年集字徽章-周
日期:2019-09-06 18:54:5415-16赛季CBA联赛之上海
日期:2018-07-25 11:55:2615-16赛季CBA联赛之青岛
日期:2018-07-10 14:13:18
4 [报告]
发表于 2007-09-14 16:18 |只看该作者
运行二楼的那一个程序的结果是:
[root@linux test]# gcc -DMEMWATCH -DMW_STDIO -I../include -o incle_mem incle_mem.c memwatch.c
[root@linux test]# ./incle_mem
Debug Memory leak
Memory malloc


.... free ....
MEMWATCH detected 2 anomalies
memwatch report error on /tmp/incle-testDIR-1557/memwatch.log

[root@linux test]# echo $?
98


运行三楼的程序的结果是:
[root@linux test]# gcc -DMEMWATCH -DMW_STDIO -I../include -o incle_mem incle_mem.c memwatch.c
[root@linux test]# ./incle_mem
Debug Memory leak
Memory malloc


.... free ....
[root@linux test]# echo $?
0

论坛徽章:
24
15-16赛季CBA联赛之北京
日期:2018-08-17 18:43:33技术图书徽章
日期:2018-08-22 12:53:57技术图书徽章
日期:2018-08-22 12:54:20技术图书徽章
日期:2018-08-22 12:54:3015-16赛季CBA联赛之福建
日期:2018-10-19 16:58:1619周年集字徽章-庆
日期:2019-08-27 13:28:5619周年集字徽章-19
日期:2019-08-27 13:31:2619周年集字徽章-19
日期:2019-08-27 13:31:2615-16赛季CBA联赛之同曦
日期:2019-09-05 12:03:2819周年集字徽章-周
日期:2019-09-06 18:54:5415-16赛季CBA联赛之上海
日期:2018-07-25 11:55:2615-16赛季CBA联赛之青岛
日期:2018-07-10 14:13:18
5 [报告]
发表于 2007-09-14 17:43 |只看该作者
眼看就要沉到底了,怎么没有人回贴呢?

论坛徽章:
0
6 [报告]
发表于 2007-09-14 19:52 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
0
7 [报告]
发表于 2007-09-15 13:27 |只看该作者
原帖由 incle 于 2007-9-14 16:01 发表
我写了个程序,进行内存测试,  
发现如果我把存在内存泄露函数放在同一个.C文件里进行编译时, 是可以检测到的,
但是如果我把这个函数放到别的文件(.H 或.C文件里), 采用包含该文件的形式进行编译测试时,就检测 ...

才知道有这么好玩的东西,去看了看文档,可惜暂时没机器测试。
不过我想不通放在.h文件里包含进来和直接写在.c里有什么不同,毕竟在预处理的时候就换成一样的了。lz再细读一下它的readme和.h文件里的文档,看有没有什么线索。

论坛徽章:
0
8 [报告]
发表于 2007-09-15 13:43 |只看该作者
关注,为什么预处理就变了

论坛徽章:
24
15-16赛季CBA联赛之北京
日期:2018-08-17 18:43:33技术图书徽章
日期:2018-08-22 12:53:57技术图书徽章
日期:2018-08-22 12:54:20技术图书徽章
日期:2018-08-22 12:54:3015-16赛季CBA联赛之福建
日期:2018-10-19 16:58:1619周年集字徽章-庆
日期:2019-08-27 13:28:5619周年集字徽章-19
日期:2019-08-27 13:31:2619周年集字徽章-19
日期:2019-08-27 13:31:2615-16赛季CBA联赛之同曦
日期:2019-09-05 12:03:2819周年集字徽章-周
日期:2019-09-06 18:54:5415-16赛季CBA联赛之上海
日期:2018-07-25 11:55:2615-16赛季CBA联赛之青岛
日期:2018-07-10 14:13:18
9 [报告]
发表于 2007-09-17 10:33 |只看该作者
原帖由 augustusqing 于 2007-9-15 13:43 发表
关注,为什么预处理就变了


多谢关注, 多谢各位大哥帮忙... 小弟现在还在研究当中, 一有结果马上贴出来...

期待更多关注和帮助...

论坛徽章:
24
15-16赛季CBA联赛之北京
日期:2018-08-17 18:43:33技术图书徽章
日期:2018-08-22 12:53:57技术图书徽章
日期:2018-08-22 12:54:20技术图书徽章
日期:2018-08-22 12:54:3015-16赛季CBA联赛之福建
日期:2018-10-19 16:58:1619周年集字徽章-庆
日期:2019-08-27 13:28:5619周年集字徽章-19
日期:2019-08-27 13:31:2619周年集字徽章-19
日期:2019-08-27 13:31:2615-16赛季CBA联赛之同曦
日期:2019-09-05 12:03:2819周年集字徽章-周
日期:2019-09-06 18:54:5415-16赛季CBA联赛之上海
日期:2018-07-25 11:55:2615-16赛季CBA联赛之青岛
日期:2018-07-10 14:13:18
10 [报告]
发表于 2007-09-28 16:39 |只看该作者
原帖由 incle 于 2007-9-14 16:16 发表
如果我把 mem_alloc() 放在另一个文件里面( incle.h)


#include

int mem_alloc(void)
{
        char *ptr1;
        char *ptr2;

        printf(" Memory malloc \n");
        if( (ptr1 = m ...

我知道这里的是由于没有增加 memwatch.h这个头文件.我加上后就完全可以得出内存泄露情况的日志了.

如果仔细看 memwatch.h里它有几个宏. (这是宏的巧妙之处)

  1. #define malloc(n)       mwMalloc(n,__FILE__,__LINE__)
  2. #define strdup(p)       mwStrdup(p,__FILE__,__LINE__)
  3. #define realloc(p,n)    mwRealloc(p,n,__FILE__,__LINE__)
  4. #define calloc(n,m)     mwCalloc(n,m,__FILE__,__LINE__)
  5. #define free(p)         mwFree(p,__FILE__,__LINE__)
  6. #define CHECK()         mwTest(__FILE__,__LINE__,MW_TEST_ALL)
  7. #define CHECK_THIS(n)   mwTest(__FILE__,__LINE__,n)
  8. #define CHECK_BUFFER(b) mwTestBuffer(__FILE__,__LINE__,b)
  9. #define MARK(p)         mwMark(p,#p,__FILE__,__LINE__)
  10. #define UNMARK(p)       mwUnmark(p,__FILE__,__LINE__)

复制代码

当你的文件里包含了这个头文件,它就会把你代码里的  malloc等函数替换成 memwatch的函数,并且从 __FILE__ 和 __LINE__
中知道你的代码哪里分配了内存等内存操作.  从而能检查你代码里的内存泄露或都溢出等情况....

至于 __FILE__ 宏的用法,大家可以参看下面:

对于一个设计好的函数,假设它已经在一个很大的工程中到处使用,突然发现它的一个不足,想修改它的功能。也许这个新增加的功能需要一个额外的参数,但是又不想修改使用这些函数的地方。 假设有两个函数必须成对使用,一个占用资源并使用,另外一个则释放资源以供其他模块使用。典型的例子是,函数一(假设为Lock)获得一个全局的锁,这个锁用于保护在多线程情况下多个线程对一个公共资源如一个全局变量的访问。问题是,这个Lock函数获得锁以后,其他线程将不能再获得这个锁,直到当前线程释放这个锁。编制Lock函数的程序员同时提供了一个 Unlock函数用于释放锁,并要求使用Lock的人必须对应的使用Unlock。调试程序时,发现线程被死锁,怀疑有人使用完Lock后忘记调用 Unlock,但是Lock和Unlock在这个大工程中都被广泛的使用,因此设计者希望Lock和Unlock都增加两个额外的参数file和line,以说明这两个函数在哪里被调用了,哪些地方被死锁以及哪些地方调用了Lock但是没有调用Unlock。 假设这两个函数的原型为:    void Lock();
    void Unlock();新设计的函数的原型是:    void Lock(LPCTSTR szFileName,UINT uLineNo);
    void Unlock(LPCTSTR szFileName,UINT uLineNo);设计完新的函数后,项目经理希望所有模块统一使用这两个函数并提供文件名和行号信息作为参数。这样将是一个非常浩大且烦琐的工作,意味着重复性的劳动、数小时无聊的加班和工期的延误,这是谁都不愿意遇到的。 使用宏可以非常轻松的解决这一切。首先,应该把新设计的函数换个名字,不妨叫它们NewLock和NewUnlock,也就是他们的原型为:    void NewLock(LPCTSTR szFileName,UINT uLineNo);
    void NewUnlock(LPCTSTR szFileName,UINT uLineNo);这个函数原型应该放在一个头文件中,避免在多个地方重复的声明。需要用到这两个函数的cpp文件,只要包含他们原型所在的头文件即可。为了不改动使用Lock/Unlock函数的模块,在头文件中增加如下两行:  #define Lock() NewLock(__FILE__,__LINE__)
  #define Unlock() NewUnlock(__FILE,__LINE__)这样,当不同模块使用这个函数时,宏替换功能在编译时起作用,自动使用了__FILE__和__LINE__为参数,调用了新设计的函数。调试的时候就可以根据日志来判断什么地方遗漏了调用Unlock。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP