Memcheck是一个内存错误检测器。它可以检测C和C ++程序中常见的以下问题:
1、非法内存:如越界、释放后继续访问;
2、使用未初始化的值;
3、释放内存错误:如double-free(同一内存上执行了两次free)、或者 malloc、new、new[] 与 free、delete、delete[]错配使用
4、memcpy函数(或其它相关函数)中src和dst指针重叠;
5、分配函数时,传递的size参数非法,如果是一个负数;
6、内存泄漏。
像这样的问题很难通过其他方式找到,经常长时间未被发现,然后造成偶然的,难以诊断的崩溃。
含义:非法读取或写入错误。
例子,main.c源码如下
#include
#include
int main()
{
int *x = (int *)malloc(sizeof(int)*10);
int i;
for(i=0; i<=10; ++i)
{
x[i] = i;//当i=10时,越界,非法访问
}
}
编译:gcc -g main.c
内存错误检查:valgrind --tool=memcheck ./a.out
错误信息如下
==20979== Memcheck, a memory error detector
==20979== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==20979== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==20979== Command: ./a.out
==20979== Parent PID: 17485
==20979==
==20979== Invalid write of size 4
==20979== at 0x400563: main (main.c:10)
==20979== Address 0x5200068 is 0 bytes after a block of size 40 alloc'd
==20979== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==20979== by 0x40053E: main (main.c:6)
==20979==
==20979==
==20979== HEAP SUMMARY:
==20979== in use at exit: 40 bytes in 1 blocks
==20979== total heap usage: 1 allocs, 0 frees, 40 bytes allocated
==20979==
==20979== LEAK SUMMARY:
==20979== definitely lost: 40 bytes in 1 blocks
==20979== indirectly lost: 0 bytes in 0 blocks
==20979== possibly lost: 0 bytes in 0 blocks
==20979== still reachable: 0 bytes in 0 blocks
==20979== suppressed: 0 bytes in 0 blocks
==20979== Rerun with --leak-check=full to see details of leaked memory
==20979==
==20979== For counts of detected and suppressed errors, rerun with: -v
==20979== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
含义:使用未初始化的值。
经常会遇到这个错误。
例子
main.c源码如下
#include
int main()
{
int x;
printf("x = %d\n",x); //此处访问未初始化的值,错误
}
编译:gcc -g main.c
内存错误检查:valgrind --tool=memcheck ./a.out
错误信息如下
==21182== Memcheck, a memory error detector
==21182== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==21182== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==21182== Command: ./a.out
==21182== Parent PID: 17485
==21182==
==21182== Conditional jump or move depends on uninitialised value(s)
==21182== at 0x4E814CE: vfprintf (vfprintf.c:1660)
==21182== by 0x4E8B3D8: printf (printf.c:33)
==21182== by 0x400548: main (main.c:6)
==21182==
==21182== Use of uninitialised value of size 8
==21182== at 0x4E8099B: _itoa_word (_itoa.c:179)
==21182== by 0x4E84636: vfprintf (vfprintf.c:1660)
==21182== by 0x4E8B3D8: printf (printf.c:33)
==21182== by 0x400548: main (main.c:6)
==21182==
==21182== Conditional jump or move depends on uninitialised value(s)
==21182== at 0x4E809A5: _itoa_word (_itoa.c:179)
==21182== by 0x4E84636: vfprintf (vfprintf.c:1660)
==21182== by 0x4E8B3D8: printf (printf.c:33)
==21182== by 0x400548: main (main.c:6)
==21182==
==21182== Conditional jump or move depends on uninitialised value(s)
==21182== at 0x4E84682: vfprintf (vfprintf.c:1660)
==21182== by 0x4E8B3D8: printf (printf.c:33)
==21182== by 0x400548: main (main.c:6)
==21182==
==21182== Conditional jump or move depends on uninitialised value(s)
==21182== at 0x4E81599: vfprintf (vfprintf.c:1660)
==21182== by 0x4E8B3D8: printf (printf.c:33)
==21182== by 0x400548: main (main.c:6)
==21182==
==21182== Conditional jump or move depends on uninitialised value(s)
==21182== at 0x4E8161C: vfprintf (vfprintf.c:1660)
==21182== by 0x4E8B3D8: printf (printf.c:33)
==21182== by 0x400548: main (main.c:6)
==21182==
==21182==
==21182== HEAP SUMMARY:
==21182== in use at exit: 0 bytes in 0 blocks
==21182== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==21182==
==21182== All heap blocks were freed -- no leaks are possible
==21182==
==21182== For counts of detected and suppressed errors, rerun with: -v
==21182== Use --track-origins=yes to see where uninitialised values come from
==21182== ERROR SUMMARY: 6 errors from 6 contexts (suppressed: 0 from 0)
可以加上选项 “–track-origins=yes”来查找,未初始化的来源,但会使Memcheck运行的更慢;
如加上选项 “–track-origins=yes”后打印信息如下
==21210== Memcheck, a memory error detector
==21210== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==21210== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==21210== Command: ./a.out
==21210== Parent PID: 17485
==21210==
==21210== Conditional jump or move depends on uninitialised value(s)
==21210== at 0x4E814CE: vfprintf (vfprintf.c:1660)
==21210== by 0x4E8B3D8: printf (printf.c:33)
==21210== by 0x400548: main (main.c:6)
==21210== Uninitialised value was created by a stack allocation
==21210== at 0x40052D: main (main.c:4)
==21210==
==21210== Use of uninitialised value of size 8
==21210== at 0x4E8099B: _itoa_word (_itoa.c:179)
==21210== by 0x4E84636: vfprintf (vfprintf.c:1660)
==21210== by 0x4E8B3D8: printf (printf.c:33)
==21210== by 0x400548: main (main.c:6)
==21210== Uninitialised value was created by a stack allocation
==21210== at 0x40052D: main (main.c:4)
==21210==
==21210== Conditional jump or move depends on uninitialised value(s)
==21210== at 0x4E809A5: _itoa_word (_itoa.c:179)
==21210== by 0x4E84636: vfprintf (vfprintf.c:1660)
==21210== by 0x4E8B3D8: printf (printf.c:33)
==21210== by 0x400548: main (main.c:6)
==21210== Uninitialised value was created by a stack allocation
==21210== at 0x40052D: main (main.c:4)
==21210==
==21210== Conditional jump or move depends on uninitialised value(s)
==21210== at 0x4E84682: vfprintf (vfprintf.c:1660)
==21210== by 0x4E8B3D8: printf (printf.c:33)
==21210== by 0x400548: main (main.c:6)
==21210== Uninitialised value was created by a stack allocation
==21210== at 0x40052D: main (main.c:4)
==21210==
==21210== Conditional jump or move depends on uninitialised value(s)
==21210== at 0x4E81599: vfprintf (vfprintf.c:1660)
==21210== by 0x4E8B3D8: printf (printf.c:33)
==21210== by 0x400548: main (main.c:6)
==21210== Uninitialised value was created by a stack allocation
==21210== at 0x40052D: main (main.c:4)
==21210==
==21210== Conditional jump or move depends on uninitialised value(s)
==21210== at 0x4E8161C: vfprintf (vfprintf.c:1660)
==21210== by 0x4E8B3D8: printf (printf.c:33)
==21210== by 0x400548: main (main.c:6)
==21210== Uninitialised value was created by a stack allocation
==21210== at 0x40052D: main (main.c:4)
==21210==
==21210==
==21210== HEAP SUMMARY:
==21210== in use at exit: 0 bytes in 0 blocks
==21210== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==21210==
==21210== All heap blocks were freed -- no leaks are possible
==21210==
==21210== For counts of detected and suppressed errors, rerun with: -v
==21210== ERROR SUMMARY: 6 errors from 6 contexts (suppressed: 0 from 0)
其中,指出未初始化的位置信息是:
==21210== Uninitialised value was created by a stack allocation
==21210== at 0x40052D: main (main.c:4)
Syscall param write(buf) points to uninitialised byte(s)
Syscall param write(buf) points to uninitialised byte(s)
含义:在系统调用中使用未初始化或不可寻址的值。
Memcheck检查系统调用的所有参数:
它会检查所有直接参数本身,无论它们是否已初始化。
此外,如果系统调用需要从程序提供的缓冲区中读取,则Memcheck会检查整个缓冲区是否可寻址并初始化其内容。
此外,如果系统调用需要写入用户提供的缓冲区,Memcheck会检查缓冲区是否可寻址。
系统调用后,Memcheck会更新其跟踪信息,以准确反映系统调用导致的内存状态的任何变化。
例子
源码main.c如下
#include
#include
int main( void )
{
char* arr = malloc(10);
int* arr2 = malloc(sizeof(int));
write( 1 /* stdout */, arr, 10 );
exit(arr2[0]);
}
编译:gcc -g main.c
内存检查:valgrind --tool=memcheck ./a.out
错误打印信息如下
==21355== Memcheck, a memory error detector
==21355== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==21355== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==21355== Command: ./a.out
==21355== Parent PID: 17485
==21355==
==21355== Syscall param write(buf) points to uninitialised byte(s)
==21355== at 0x4F263C0: __write_nocancel (syscall-template.S:81)
==21355== by 0x4005F6: main (main.c:7)
==21355== Address 0x5200040 is 0 bytes inside a block of size 10 alloc'd
==21355== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==21355== by 0x4005CE: main (main.c:5)
==21355== Uninitialised value was created by a heap allocation
==21355== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==21355== by 0x4005CE: main (main.c:5)
==21355==
==21355== Syscall param exit_group(status) contains uninitialised byte(s)
==21355== at 0x4EFC109: _Exit (_exit.c:32)
==21355== by 0x4E7316A: __run_exit_handlers (exit.c:97)
==21355== by 0x4E731F4: exit (exit.c:104)
==21355== by 0x400603: main (main.c:8)
==21355== Uninitialised value was created by a heap allocation
==21355== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==21355== by 0x4005DC: main (main.c:6)
==21355==
==21355==
==21355== HEAP SUMMARY:
==21355== in use at exit: 14 bytes in 2 blocks
==21355== total heap usage: 2 allocs, 0 frees, 14 bytes allocated
==21355==
==21355== LEAK SUMMARY:
==21355== definitely lost: 0 bytes in 0 blocks
==21355== indirectly lost: 0 bytes in 0 blocks
==21355== possibly lost: 0 bytes in 0 blocks
==21355== still reachable: 14 bytes in 2 blocks
==21355== suppressed: 0 bytes in 0 blocks
==21355== Rerun with --leak-check=full to see details of leaked memory
==21355==
==21355== For counts of detected and suppressed errors, rerun with: -v
==21355== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
含义:非法释放。
例子
源码main.c如下:
#include
#include
int main( void )
{
char* arr = malloc(10);
free(arr);
free(arr);
return 0;
}
编译:gcc -g main.c
内存检查:valgrind --tool=memcheck ./a.out
错误打印信息如下
==21442== Memcheck, a memory error detector
==21442== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==21442== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==21442== Command: ./a.out
==21442== Parent PID: 17485
==21442==
==21442== Invalid free() / delete / delete[] / realloc()
==21442== at 0x4C2BDEC: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==21442== by 0x4005AA: main (main.c:7)
==21442== Address 0x5200040 is 0 bytes inside a block of size 10 free'd
==21442== at 0x4C2BDEC: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==21442== by 0x40059E: main (main.c:6)
==21442==
==21442==
==21442== HEAP SUMMARY:
==21442== in use at exit: 0 bytes in 0 blocks
==21442== total heap usage: 1 allocs, 2 frees, 10 bytes allocated
==21442==
==21442== All heap blocks were freed -- no leaks are possible
==21442==
==21442== For counts of detected and suppressed errors, rerun with: -v
==21442== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
含义:分配内存和释放内存方法不匹配。
例子:使用malloc分配内存,然后使用delete释放就会报这个错误。
源码main.c
#include
#include
int main( void )
{
char* arr = (char*)malloc(10);
delete arr;
return 0;
}
使用G++编译:g++ -g main.c
内存检查:valgrind --tool=memcheck ./a.out
错误打印信息如下
==21579== Memcheck, a memory error detector
==21579== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==21579== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==21579== Command: ./a.out
==21579== Parent PID: 17485
==21579==
==21579== Mismatched free() / delete / delete []
==21579== at 0x4C2C2BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==21579== by 0x40066E: main (main.c:6)
==21579== Address 0x5a20040 is 0 bytes inside a block of size 10 alloc'd
==21579== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==21579== by 0x40065E: main (main.c:5)
==21579==
==21579==
==21579== HEAP SUMMARY:
==21579== in use at exit: 0 bytes in 0 blocks
==21579== total heap usage: 1 allocs, 1 frees, 10 bytes allocated
==21579==
==21579== All heap blocks were freed -- no leaks are possible
==21579==
==21579== For counts of detected and suppressed errors, rerun with: -v
==21579== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
含义:下面的C库函数从一个存储器块复制一些数据到另一个memcpy、 strcpy、strncpy、strcat、strncat它们src和 dst指针指向的块不允许重叠。POSIX标准的措辞如下:“如果在重叠的对象之间进行复制,则行为未定义。” 因此,Memcheck会检查这一点。
例子
源码main.c如下:
#include
int main( void )
{
char a[12] = {'h','e','l', 'l','o','\0'};
memcpy(a+3,a,6);
return 0;
}
编译:gcc -g main.c
内存检查:valgrind --tool=memcheck ./a.out
错误打印信息如下
==22017== Memcheck, a memory error detector
==22017== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==22017== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==22017== Command: ./a.out
==22017==
==22017== Source and destination overlap in memcpy(0xffefffbc3, 0xffefffbc0, 6)
==22017== at 0x4C2F71C: memcpy@@GLIBC_2.14 (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==22017== by 0x400613: main (main.c:6)
==22017==
==22017==
==22017== HEAP SUMMARY:
==22017== in use at exit: 0 bytes in 0 blocks
==22017== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==22017==
==22017== All heap blocks were freed -- no leaks are possible
==22017==
==22017== For counts of detected and suppressed errors, rerun with: -v
==22017== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
疑问,当我用memcpy(a, a, 6);时,没有报错,哪位大神给解释下?
含义:可疑的参数值。
所有内存分配函数都使用一个参数来指定应分配的内存块的大小。显然,请求的大小应该是非负值,并且通常不会过大。例如,在64位计算机上,分配请求的大小超过2 ** 63字节或者是负值。这样的值被称为“可疑的值”。
下列函数中的size参数将被检查: malloc、calloc、 realloc、memalign、new、 new []、 __builtin_new、 __builtin_vec_new,对于calloc 两个参数都在检查中。
例子
源码main.c如下
#include
#include
int main( void )
{
char* arr = (char *)malloc(-1);
free(arr);
return 0;
}
编译:gcc -g main.c
内存检查:valgrind --tool=memcheck ./a.out
错误打印信息如下
==22177== Memcheck, a memory error detector
==22177== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==22177== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==22177== Command: ./a.out
==22177==
==22177== Argument 'size' of function malloc has a fishy (possibly negative) value: -1
==22177== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==22177== by 0x400590: main (main.c:5)
==22177==
==22177==
==22177== HEAP SUMMARY:
==22177== in use at exit: 0 bytes in 0 blocks
==22177== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==22177==
==22177== All heap blocks were freed -- no leaks are possible
==22177==
==22177== For counts of detected and suppressed errors, rerun with: -v
==22177== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
含义:内存泄漏检查。
Memcheck跟踪malloc/new函数对应的free/delete等的调用,因此,当程序退出时,它知道哪些块未被释放。
此功能需要设置参数–leak-check=summary或full。
例子
源码main.c如下
#include
#include
int main( void )
{
char* arr = (char *)malloc(4);
//free(arr);//此处没有释放
return 0;
}
编译:gcc -g main.c
内存检查:valgrind --tool=memcheck --leak-check=full ./a.out
错误打印信息如下
==22289== Memcheck, a memory error detector
==22289== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==22289== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==22289== Command: ./a.out
==22289==
==22289==
==22289== HEAP SUMMARY:
==22289== in use at exit: 4 bytes in 1 blocks
==22289== total heap usage: 1 allocs, 0 frees, 4 bytes allocated
==22289==
==22289== 4 bytes in 1 blocks are definitely lost in loss record 1 of 1
==22289== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==22289== by 0x40053E: main (main.c:5)
==22289==
==22289== LEAK SUMMARY:
==22289== definitely lost: 4 bytes in 1 blocks
==22289== indirectly lost: 0 bytes in 0 blocks
==22289== possibly lost: 0 bytes in 0 blocks
==22289== still reachable: 0 bytes in 0 blocks
==22289== suppressed: 0 bytes in 0 blocks
==22289==
==22289== For counts of detected and suppressed errors, rerun with: -v
==22289== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
LEAK SUMMARY:内存泄漏总结(分类)
definitely lost: 4 bytes in 1 blocks:绝对丢失,这种情况应该由程序员来解决,下面几种情况,可以当作参考
indirectly lost: 0 bytes in 0 blocks:间接丢失
possibly lost: 0 bytes in 0 blocks:可能丢失
still reachable: 0 bytes in 0 blocks:仍然可以访问
suppressed: 0 bytes in 0 blocks:抑制错误中的丢失