内存检测工具"/>
Valgrind——c/c++内存检测工具
文章目录
- 前言
- 检测说明
- 泄露类型说明
- memcheck指令
- references
前言
Valgrind 是一个用于构建动态分析工具的检测框架。
Valgrind包含了可以自动检测多种内存管理和线程错误的工具,并对程序进行详细的分析。而且,还可以使用Valgrind来构建新工具。
检测说明
Valgrind是检测内存泄露工具,可检测如下几种内存泄露风险
No. | type |
---|---|
1 | Illegal read / Illegal write errors |
2 | Use of uninitialized values |
3 | Use of uninitialized or unaddressable values in system calls |
4 | Illegal frees |
5 | When a heap block is freed with an inappropriate deallocation function |
6 | Overlapping source and destination blocks |
7 | Fishy argument values |
泄露类型说明
编译时注意加-g选项
- Illegal read / Illegal write errors
表示续写了还未分配的内存块、读写已经被free的内存块或内存访问越界(包括超出堆中内存块的范围、访问了栈中不能访问的区域)。使用–read-var-info=yes选项可直详细原因。
int main()
{void* p = malloc(1);free(p);*(char*)p = '2';
}
==40816== Invalid write of size 1
==40816== at 0x1091D3: main (test.cpp:22)
==40816== Address 0x4ddfc80 is 0 bytes inside a block of size 1 free'd
==40816== at 0x484B27F: free (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==40816== by 0x1091CE: main (test.cpp:21)
==40816== Block was alloc'd at
==40816== at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==40816== by 0x1091BE: main (test.cpp:20)
- Use of uninitialized values
检测是否使用未初始化的值。有两种未初始化的成因:(1)函数中的局部变量没有被初始化。类的成员为基本类型,默认构造函数则什么也不做,如果直接使用该类对象的值;(2)堆上的内存块,在使用之前没有被初始化。使用malloc或new/new[]基本类型则返回的内存块为随机值。使用选项–track-origins=yes可知详细原因
class test
{
public:int a;int b;void* c;
public:test(/* args */) = default;~test() = default;
};int main()
{test t;printf("%d, %p\n", t.a, t.c);
}
编译时注意加-g选项
==40576== Conditional jump or move depends on uninitialised value(s)
==40576== at 0x4B0FE85: __vfprintf_internal (vfprintf-internal.c:1516)
==40576== by 0x4AFA79E: printf (printf.c:33)
==40576== by 0x1091DE: main (test.cpp:21)
==40576== Uninitialised value was created by a stack allocation
==40576== at 0x1091A9: main (test.cpp:19)
-
Use of uninitialized or unaddressable values in system calls
检测系统调用是否已经初始化。如果要读程序提供的buffer,会检测buffer是否addressable以及是否初始化。如果要写程序提供的buffer,会检查buffer是否addressable。 -
Illegal free
检测是否重复释放内存块,或者指针没有指向内存的起始位置
int main()
{void* p = malloc(1);free(p);free(p);
}
==41017== Invalid free() / delete / delete[] / realloc()
==41017== at 0x484B27F: free (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==41017== by 0x1091DA: main (test.cpp:22)
==41017== Address 0x4ddfc80 is 0 bytes inside a block of size 1 free'd
==41017== at 0x484B27F: free (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==41017== by 0x1091CE: main (test.cpp:21)
==41017== Block was alloc'd at
==41017== at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==41017== by 0x1091BE: main (test.cpp:20)
- When a heap block is freed with an inappropriate deallocation function
c++内存申请和释放的配对要求(进一步体现了c++的复杂性)
分配函数 | 释放函数 |
---|---|
malloc, calloc, realloc, valloc, memalign | free |
new | delete |
new[] | delete[] |
- Overlapping source and destination blocks
检测内存覆盖,及memcpy, strcpy, strncpy, strcat, strncat等函数的源和目的内存块是否有重叠。如果这些函数的源内存块和目的内存块有重叠,结果可能出错。
#define ADDR_ADD(addr, num) ((char*)addr + num)
int main()
{void* p = malloc(10);strncpy(ADDR_ADD(p, 1), (const char*)p, 5);free(p);
}
==41569== Conditional jump or move depends on uninitialised value(s)
==41569== at 0x484F02A: strncpy (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==41569== by 0x1091FE: main (test.cpp:25)
- Fishy argument values
检测需要的内存大小是否是负数或者过大
==41798== Argument 'size' of function malloc has a fishy (possibly negative) value: -10
==41798== at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==41798== by 0x1091C0: main (test.cpp:25)
memcheck指令
分析内存泄露问题建议在终端中输入以下命令,可输出检测log文件
valgrind --tool=memcheck --leak-check=full --show-leak-kinds=all --log-file=res.log ./a.out
1--tool=memcheck: (--tool=<toolname>[default: memcheck])表示使用memcheck工具,默认是使用memcheck
2--leak-check=full: (--leak-check=<no|summary|yes|full>[default:summary])决定了输出泄露结果时,输出的内容。no:没输出,summary:只输出统计结果,yes和full输出详细内容
3-show-leak-kinds=all(--show-leak-kinds=[default:definite, possible]) valgrind有4种泄露类型,这个参数决定显示哪些类型泄露。可以设置多个以逗号相隔,也可以用all表示全部类型,none表示不显示
4--log-file=log(--log-file=<filename>[default:2, stderr])valgrind打印log转存到指定文件。如果未使用这个参数valgrind的log会连同程序的log一起输出
references
/
更多推荐
Valgrind——c/c++内存检测工具
发布评论