Valgrind概述
内存分析工具Valgrind是一套Linux下的开放源代码的仿真调试工具的集合。Valgrind由内核以及基于内核的其他调试工具组成。
Valgrind包括以下一些工具:
- Memcheck:这是Valgrind应用最广泛的内存检查器,能够发现开发中绝大多数内存错误使用情况,比如:使用未初始化的内存、使用已经释放的内存、内存访问越界等。
- Callgrind
- Cachegrind
- Helgrind
- Massif
- Extension
Memcheck内存检查原理
Memcheck能够检测出内存问题,关键在于建立了两个全局表:
- Valid-Value表:我们知道,对于进程的整个地址空间中的每一个字节,都有与之对应的8bit;同样,对于CPU的每个寄存器,也有一个与之对应的bit向量。这些bit负责记录该字节或者寄存器值是否具有有效的、已初始化的值。
- Valid-Address表:对于进程整个地址空间中的每一个字节,还有与之对应的1bit,负责记录该地址是否能够被读写。
- 检测原理:
- 当要读写内存中某个字节时,首先检测这个字节对应的A bit。如果该A bit显示该位置是无效位置,Memcheck则报告读写错误。
- 一旦寄存器中的值,被用来产生内存地址,或者该值能够影响程序输出,则Memcheck会检查对应的V bit,如果该值尚未初始化,则会报告使用未初始化内存错误。
- 常见的内存错误使用情况:
- 使用未初始化的内存:位于程序中不同段的变量,其初始值是不同的,全局变量和静态变量初始值为0,而局部变量和动态申请的变量,其初始值为随机值。
- 内存读写越界:访问了没有权限访问的内存地址空间,如访问数组时越界、对动态内存访问时超出了申请的内存大小范围。
- 内存覆盖:对于strcpy、strncpy、memcpy、strcat等,这些函数需要设置源地址(src)和目标地址(dst),且src和dst指向的地址不能发生重叠,否则结果将不可预期。
- 动态内存管理错误:(1)申请和释放不一致;(2)申请和释放不匹配;(3)释放后仍然读写。程序非法读写内存都不一定会出现coredump,但释放无效内存一定会出现coredump。
- 内存泄漏:在程序中动态申请的内存,在使用完后既没有释放,又无法被程序其他部分访问。