先看看输出信息中的HEAP SUMMARY,它表示程序在堆上分配内存的情况,其中的1 allocs
表示程序分配了 1 次内存,0 frees表示程序释放了 0 次内存,10 bytes allocated表示分配了 10 个字节的内存。
另外,Valgrind 也会报告程序是在哪个位置发生内存泄漏。
上面LEAK SUMMARY会打印5种不同的类型,这里我们简单介绍一下:
definitely lost: 明确丢失的内存。程序中存在内存泄露,应尽快修复。当程序结束时如果一块动态分配的内存没有被释放并且通过程序内的指针变量均无法访问这块内存则会报这个错误; indirectly lost: 间接丢失。当使用了含有指针成员的类或结构体时可能会报这个错误。这类错误无需直接修复,它们总是与definitely lost一起出现,只要修复definitely lost即可。 possibly lost: 可能丢失。大多数情况下应视为与definitely lost一样需要尽快修复,除非你的程序让一个指针指向一块动态分配的内存(但不是这块内存的起始地址),然后通过运算得到这块内存的起始地址,再释放它。当程序结束时如果一块动态分配的内存没有被释放并且通过程序内的指针变量均无法访问这块内存的起始地址,但可以访问其中的某一部分数据,则会报这个错误。 stil reachable: 可以访问,未丢失但也未释放。如果程序是正常结束的,那么它可能不会造成程序崩溃,但长时间运行有可能耗尽系统资源。其他几种情况,写一个综合的测试程序进行验证。
// mixed.cpp void func() { char *ptr = new char[10]; ptr[10] = 'a'; // 内存越界 memcpy(ptr + 1, ptr, 5); // 踩内存 delete []ptr; delete []ptr; // 重复释放 char *p; *p = 1; // 非法指针 } int main() { func(); return 0; }编译后,用valgrind检测程序。
$ g++ -g -o test mixed.cpp $ valgrind --tool=memcheck --leak-check=full ./test检测结果
==22786== Memcheck, a memory error detector ==22786== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. ==22786== Using Valgrind-3.16.1 and LibVEX; rerun with -h for copyright info ==22786== Command: ./test ==22786== ==22786== Invalid write of size 1 // 内存越界 ==22786== at 0x4007FB: func() (mixed.cpp:6) ==22786== by 0x400851: main (mixed.cpp:18) ==22786== Address 0x5a2404a is 0 bytes after a block of size 10 alloc'd ==22786== at 0x4C2AC58: operator new[](unsigned long) (vg_replace_malloc.c:431) ==22786== by 0x4007EE: func() (mixed.cpp:5) ==22786== by 0x400851: main (mixed.cpp:18) ==22786== ==22786== Source and destination overlap in memcpy(0x5a24041, 0x5a24040, 5) // 踩内存 ==22786== at 0x4C2E83D: memcpy@@GLIBC_2.14 (vg_replace_strmem.c:1033) ==22786== by 0x400819: func() (mixed.cpp:8) ==22786== by 0x400851: main (mixed.cpp:18) ==22786== ==22786== Invalid free() / delete / delete[] / realloc() // 重复释放 ==22786== at 0x4C2BBAF: operator delete[](void*) (vg_replace_malloc.c:649) ==22786== by 0x40083F: func() (mixed.cpp:11) ==22786== by 0x400851: main (mixed.cpp:18) ==22786== Address 0x5a24040 is 0 bytes inside a block of size 10 free'd ==22786== at 0x4C2BBAF: operator delete[](void*) (vg_replace_malloc.c:649) ==22786== by 0x40082C: func() (mixed.cpp:10) ==22786== by 0x400851: main (mixed.cpp:18) ==22786== Block was alloc'd at ==22786== at 0x4C2AC58: operator new[](unsigned long) (vg_replace_malloc.c:431) ==22786== by 0x4007EE: func() (mixed.cpp:5) ==22786== by 0x400851: main (mixed.cpp:18) ==22786== ==22786== Use of uninitialised value of size 8 // 非法指针 ==22786== at 0x400844: func() (mixed.cpp:14) ==22786== by 0x400851: main (mixed.cpp:18) ==22786== ==22786== ==22786== Process terminating with default action of signal 11 (SIGSEGV): dumping core ==22786== Bad permissions for mapped region at address 0x4008B0 ==22786== at 0x400844: func() (mixed.cpp:14) ==22786== by 0x400851: main (mixed.cpp:18) ==22786== ==22786== HEAP SUMMARY: ==22786== in use at exit: 0 bytes in 0 blocks ==22786== total heap usage: 1 allocs, 2 frees, 10 bytes allocated ==22786== ==22786== All heap blocks were freed -- no leaks are possible ==22786== ==22786== Use --track-origins=yes to see where uninitialised values come from ==22786== For lists of detected and suppressed errors, rerun with: -s ==22786== ERROR SUMMARY: 4 errors from 4 contexts (suppressed: 0 from 0) Segmentation fault (core dumped)可见valgrind将上述几种情况都检测出来了。
2) Callgrind