聊一聊 Valgrind 监视非托管内存泄露和崩溃

打印 上一主题 下一主题

主题 905|帖子 905|积分 2715

一:背景

1. 讲故事

只要是程序总会出现各种莫名其妙的问题,比如:非托管内存泄露,程序崩溃,在 Windows 平台上一般用微软自家的官方工具 App Verifier 就可以洞察,那问题出在 Linux 上怎么办呢?由于 Linux 崇尚自由,需要在各种牛鬼蛇神写的非官方开源软件中寻找一个比较靠谱的,比如本篇所说的 Valgrind。
个人感觉 Valgrind 和 App Verifer 定位是差不多的,技术上前者使用 hook 钩子,后者使用仿真cpu,有点像 windbg 的 TTD 调试,具体信息参考:https://valgrind.org/
二:Valgrind 内存洞察

1. 安装

如果你用的是 ubuntu,可以用 apt-get 直接安装,方便快捷,目前最新的版本是 3.15.0 。
  1. root@skyfly-virtual-machine:/home/skyfly/Desktop# apt-get install valgrind
  2. Reading package lists... Done
  3. Building dependency tree      
  4. Reading state information... Done
  5. valgrind is already the newest version (1:3.15.0-1ubuntu9.1).
  6. 0 upgraded, 0 newly installed, 0 to remove and 23 not upgraded.
  7. root@skyfly-virtual-machine:/home/skyfly/Desktop# valgrind --version
  8. valgrind-3.15.0
复制代码
2. 内存泄露洞察

内存泄露大多是 new/delete , malloc/free 不匹配造成的,接下来写一个不匹配的 malloc/free 观察下。
  1. #include <iostream>
  2. #include <stdio.h>
  3. using namespace std;
  4. int main(void)
  5. {
  6.     int *p = (int *)malloc(4);
  7.     *p = 10;
  8.    
  9.     printf("p=%d", *p);
  10.     return EXIT_SUCCESS;
  11. }
复制代码
这里使用 vscode 进行编译,怎么编译就不说了,参见上一篇,接下来用 algrind --leak-check=full ./main.out 以仿真的方式把程序跑起来,截图如下:

从图中的 HEAP SUMMARY 区域可以看到,当前有 3 个 malloc,但只有 2 个 free,而且还找到了那个没有 free 的 malloc,在代码的 main.cpp:8 行,即 int *p = (int *)malloc(4); 处。

3. 栈溢出洞察

相信经常写递归的朋友总会遇到这类问题,为了方便演示,我故意实现一个 栈上溢 的例子吧。
  1. #include <iostream>
  2. #include <stdio.h>
  3. using namespace std;
  4. int main(void)
  5. {
  6.     int num = 10;
  7.     int *ptr = &num;
  8.     ptr -= 0x40;
  9.     *ptr = 15;
  10.     return EXIT_SUCCESS;
  11. }
复制代码

从图中可以清晰的看到,主线程栈上的地址 0x1ffefffd5c 无法写入,还指出了在 main.cpp:12 行,即 *ptr = 15; 处。
为了方便验证,这里用 g++ 调试的方式洞察一下。
  1. -exec p num
  2. $5 = 10
  3. -exec x ptr
  4. 0x7fffffffde2c:        0xf7fb0e9800007fff
  5. -exec info reg
  6. ...
  7. rbp            0x7fffffffdf40      0x7fffffffdf40
  8. rsp            0x7fffffffdf20      0x7fffffffdf20
  9. ...
复制代码
从输出看,ptr 已经逃出了 rsp ~ rbp 范围之内,很明显上溢了,如果用 x 命令观察的话,可以看到里面的内容就很随机,在 windbg 中用以 ??? 来表示的。
  1. -exec x ptr
  2. 0x7fffffffde2c:        0xf7fb0e9800007fff
  3. -exec x 0xf7fb0e9800007fff
  4. 0xf7fb0e9800007fff:        Cannot access memory at address 0xf7fb0e9800007fff
复制代码
除了观察 rsp,rbp,还可以看虚拟地址中的 stack 空间。
  1. -exec i proc mapping
  2. process 8327
  3. Mapped address spaces:
  4.           Start Addr           End Addr       Size     Offset objfile
  5.       ...
  6.           0x7ffff7ffd000     0x7ffff7ffe000     0x1000    0x2d000 /usr/lib/x86_64-linux-gnu/ld-2.31.so
  7.       0x7ffff7ffe000     0x7ffff7fff000     0x1000        0x0
  8.       0x7ffffffde000     0x7ffffffff000    0x21000        0x0 [stack]
复制代码
4. 数组越界洞察

valgrind 这玩意也有弱鸡的时候,比如数组越界之类的问题它就搞不定,比如下面的代码:
  1. #include <iostream>
  2. #include <stdio.h>
  3. using namespace std;
  4. int main(void)
  5. {
  6.     int num[5] = {1, 2, 3, 4, 5};
  7.     int num2[10];
  8.     num[6] = 15;
  9.     return EXIT_SUCCESS;
  10. }
复制代码
通过下面的汇编代码观察,可以看到目前分配了 0x30 = 0n48 byte 的栈空间,截图如下:

虽然 num[6] 是越界操作,但是在合理的 栈空间 内,这种仿生cpu的方式洞察不出来,App Verifier 这种 hook 的方式是没有问题的。
接下来用 valgrind 尝试一下,可以看到果然没发现任何问题,输出如下:
  1. skyfly@skyfly-virtual-machine:~/code$ valgrind ./main.out
  2. ==10244== Memcheck, a memory error detector
  3. ==10244== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
  4. ==10244== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
  5. ==10244== Command: ./main.out
  6. ==10244==
  7. ==10244==
  8. ==10244== HEAP SUMMARY:
  9. ==10244==     in use at exit: 0 bytes in 0 blocks
  10. ==10244==   total heap usage: 1 allocs, 1 frees, 72,704 bytes allocated
  11. ==10244==
  12. ==10244== All heap blocks were freed -- no leaks are possible
  13. ==10244==
  14. ==10244== For lists of detected and suppressed errors, rerun with: -s
  15. ==10244== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
复制代码
三:总结

总的来说,Valgrind 在洞察内存方面还是非常强大的,但也有它不能触及到的地方,熟悉它的优点和缺点,全面了解对我们调试师来说至关重要,希望本篇对你有帮助。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

欢乐狗

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表