Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3885090
  • 博文数量: 146
  • 博客积分: 3918
  • 博客等级: 少校
  • 技术积分: 8585
  • 用 户 组: 普通用户
  • 注册时间: 2010-10-17 13:52
个人简介

个人微薄: weibo.com/manuscola

文章分类

全部博文(146)

文章存档

2016年(3)

2015年(2)

2014年(5)

2013年(42)

2012年(31)

2011年(58)

2010年(5)

分类: C/C++

2012-04-03 13:13:08

    上一篇提到了mtrace,是个好东东,除了mtrace外还有个一个不错的,设置好MEM_CHECK_,也可以很好的定位malloc free之类的错误。

    闲言不多说,先上代码:
    
  1. #include
  2. #include
  3. int free_inside(int * p)
  4. {
  5.     if(p)
  6.         free(p);
  7. }
  8. int main()
  9. {
  10.     int *p = malloc(100*sizeof(int));

  11.     free_inside(p);
  12.     free(p);
  13.     return 0;
  14. }
我们可以看到,p指向的内存被释放了两次,第二次释放一定会出问题。

  1. root@libin:~/program/C/mem_bug# env MALLOC_CHECK_=1 ./test
  2. *** glibc detected *** ./test: free(): invalid pointer: 0x08d22008 ***
  3. root@libin:~/program/C/mem_bug# ./test
  4. *** glibc detected *** ./test: double free or corruption (top): 0x0943e008 ***
  5. ======= Backtrace: =========
  6. /lib/tls/i686/cmov/libc.so.6(+0x6b591)[0xba4591]
  7. /lib/tls/i686/cmov/libc.so.6(+0x6cde8)[0xba5de8]
  8. /lib/tls/i686/cmov/libc.so.6(cfree+0x6d)[0xba8ecd]
  9. ./test[0x804845e]
  10. /lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xe6)[0xb4fbd6]
  11. ./test[0x8048381]
  12. ======= Memory map: ========
  13. 00526000-00541000 r-xp 00000000 08:0a 532971 /lib/ld-2.11.1.so
  14. 00541000-00542000 r--p 0001a000 08:0a 532971 /lib/ld-2.11.1.so
  15. 00542000-00543000 rw-p 0001b000 08:0a 532971 /lib/ld-2.11.1.so
  16. 0060e000-0060f000 r-xp 00000000 00:00 0 [vdso]
  17. 00b39000-00c8c000 r-xp 00000000 08:0a 534966 /lib/tls/i686/cmov/libc-2.11.1.so
  18. 00c8c000-00c8d000 ---p 00153000 08:0a 534966 /lib/tls/i686/cmov/libc-2.11.1.so
  19. 00c8d000-00c8f000 r--p 00153000 08:0a 534966 /lib/tls/i686/cmov/libc-2.11.1.so
  20. 00c8f000-00c90000 rw-p 00155000 08:0a 534966 /lib/tls/i686/cmov/libc-2.11.1.so
  21. 00c90000-00c93000 rw-p 00000000 00:00 0
  22. 00eed000-00f0a000 r-xp 00000000 08:0a 524925 /lib/libgcc_s.so.1
  23. 00f0a000-00f0b000 r--p 0001c000 08:0a 524925 /lib/libgcc_s.so.1
  24. 00f0b000-00f0c000 rw-p 0001d000 08:0a 524925 /lib/libgcc_s.so.1
  25. 08048000-08049000 r-xp 00000000 08:0b 1052377 /home/libin/program/C/mem_bug/test
  26. 08049000-0804a000 r--p 00000000 08:0b 1052377 /home/libin/program/C/mem_bug/test
  27. 0804a000-0804b000 rw-p 00001000 08:0b 1052377 /home/libin/program/C/mem_bug/test
  28. 0943e000-0945f000 rw-p 00000000 00:00 0 [heap]
  29. b7700000-b7721000 rw-p 00000000 00:00 0
  30. b7721000-b7800000 ---p 00000000 00:00 0
  31. b78a5000-b78a6000 rw-p 00000000 00:00 0
  32. b78bc000-b78be000 rw-p 00000000 00:00 0
  33. bf917000-bf92c000 rw-p 00000000 00:00 0 [stack]
  34. 已放弃
    比较有用的信息是backtrace打印出来的堆栈调用关系,有了这个,我们就可以方便的利用objdump出来的汇编代码,定位问题,其中,报错很明白的告诉我们是double free,重复释放内存的问题。效果很好

  1. *** glibc detected *** ./test: double free or corruption (top): 0x0943e008 ***


参考文献:
   DEBUG HACKS
阅读(7085) | 评论(5) | 转发(1) |
给主人留下些什么吧!~~

Heartwork2012-04-04 22:20:43

buddy system一般在分配大小不定的内存块时使用。
调试版本中加入这文件名、代码行数等调试信息,release版本去掉就好了。
因为之前的工作就是开发和维护底层的中间件代码库,内存这块的主要问题就是double free和memory leak,所以有点心得,呵呵。

Bean_lee2012-04-04 22:15:18

Heartwork: malloc内部实现也是一个buddy system,应该可以通过内存块的头部发现内存是否已经分配,从而发现double free的错误。如果要是能够帮助定位第一次free的位置就更.....
伙伴内存系统是内核模块,我们能定制吗?让内存块的头部记录文件名和行数不好办吧。记录下汇编指令地址就好了。

呵呵兄弟果然是常查bug之人啊,能看出问题关键之所在。

Heartwork2012-04-04 22:10:41

malloc内部实现也是一个buddy system,应该可以通过内存块的头部发现内存是否已经分配,从而发现double free的错误。如果要是能够帮助定位第一次free的位置就更好了,可以在内存block的头部记录free时的文件名和代码行数(__FILE__和__LINE__),这样可以在调试版本中帮助发现内存分配的逻辑错误。

Bean_lee2012-04-03 14:14:35

呵呵,你说的valgrind,久仰大名,还没用过,呵呵,好久不写了开开张。
假期主要任务还是研究sqlite。

GFree_Wind2012-04-03 14:12:00

我也看了这本书了。但是感觉关于内存的检查,还是valgrind更方便。