目录
valgrind简介
valgrind 是一个提供了一些 debug 和优化的工具的工具箱,可以使得你的程序减少内存泄漏或者错误访问,valgrind 默认使用 memcheck 去检查内存问题.
memcheck 检测内存问题的原理
Memcheck 能够检测出内存问题,关键在于其建立了两个全局表。
- valid-value map:
对于进程的整个地址空间中的每一个字节(byte),都有与之对应的 8 个 bits;对于 CPU 的每个寄存器,也有一个与之对应的 bit 向量。这些 bits 负责记录该字节或者寄存器值是否具有有效的、已初始化的值。- valid-address map
对于进程整个地址空间中的每一个字节(byte),还有与之对应的 1 个 bit,负责记录该地址是否能够被读写。
memcheck检测原理
- 当要读写内存中某个字节时,首先检查 valid-address map 中这个字节对应的 A bit。如果该A bit显示该位置是无效位置,memcheck 则报告读写错误。
- 内核(core)类似于一个虚拟的 CPU 环境,这样当内存中的某个字节被加载到真实的 CPU 中时,该字节对应的 V bit (在 valid-value map 中) 也被加载到虚拟的 CPU 环境中。一旦寄存器中的值,被用来产生内存地址,或者该值能够影响程序输出,则 memcheck 会检查对应的 V bits,如果该值尚未初始化,则会报告使用未初始化内存错误。
valgrind安装流程
sudo apt-get install valgrind
删除所有日志:
rm valgrind.log.*
在命令memcheck下,启动:
G_SLICE=always-malloc G_DEBUG=gc-friendly valgrind -v --tool=memcheck --leak-check=full --num-callers=40 --log-file=valgrind.log <program> <arguments>
查看帮助文档:
valgrind --help
使用valgrind带有的memcheck工具检查内存泄漏情况:
Memcheck是一个内存错误检测器。它可以检测C和c++程序中常见的下列问题。
访问你不应该访问的内存,例如溢出或欠运行堆块,溢出堆栈顶部,以及在释放内存后访问内存。
使用未定义的值,即未初始化的值,或从其他未定义的值派生的值。
不正确地释放堆内存,例如双重释放堆块,或者不匹配地使用malloc/new/new[]与free/delete/delete[]
memcpy和相关函数中的src和dst指针重叠。
内存泄漏。
valgrind --tool=[memcheck]
报错:valgrind: failed to start tool '[memcheck]' for platform 'arm-linux': No such file or directory
解决:我的ubuntu系统是32位,valgrint是64位的
char *p;
printf("%d\n",sizeof(p));
使用以下命令执行程序:
G_SLICE=always-malloc G_DEBUG=gc-friendly valgrind -v --tool=memcheck --leak-check=full --num-callers=40 --log-file=valgrind.log <program> <arguments>
执行异常结束,出现了Killed字样
查看valgrind日志
cat valgrind.log
就可以知道出错的情况了
常见的内存问题
【参考自valgrind 的使用 - 简书 (jianshu.com)】
使用了未初始化的内存
内存读写越界
动态内存管理错误
- 申请和释放不一致
由于 C++ 兼容 C,而 C 与 C++ 的内存申请和释放函数是不同的,因此在 C++ 程序中,就有两套动态内存管理函数。一条不变的规则就是采用 C 方式申请的内存就用 C 方式释放;用 C++ 方式申请的内存,用 C++ 方式释放。也就是用 malloc/alloc/realloc 方式申请的内存,用 free 释放;用 new 方式申请的内存用 delete 释放。在上述程序中,用 malloc 方式申请了内存却用 delete 来释放,虽然这在很多情况下不会有问题,但这绝对是潜在的问题。 - 申请和释放不匹配
申请了多少内存,在使用完成后就要释放多少。如果没有释放,或者少释放了就是内存泄露;多释放了也会产生问题。 - 释放后仍然读写
本质上说,系统会在堆上维护一个动态内存链表,如果被释放,就意味着该块内存可以继续被分配给其他部分,如果内存被释放后再访问,就可能覆盖其他部分的信息,这是一种严重的错误。