如何使用Valgrind memcheck工具进行C/C++的内存泄漏检测
2个回答
2016-04-09 · 做真实的自己 用良心做教育
千锋教育
千锋教育专注HTML5大前端、JavaEE、Python、人工智能、UI&UE、云计算、全栈软件测试、大数据、物联网+嵌入式、Unity游戏开发、网络安全、互联网营销、Go语言等培训教育。
向TA提问
关注
展开全部
使用 Valgrind Memcheck
memcheck工具的使用方式如下:
valgrind --tool=memcheck ./a.out
从上面的命令可以清楚的看到, 主要的命令是valgrind,而我们想使用的工具是通过'-tool'选项来指定的. 上面的‘a.out’指的是我们想使用memcheck运行的可执行文件.
该工具可以检测下列与内存相关的问题 :
未释放内存的使用
对释放后内存的读/写
对已分配内存块尾部的读/写
内存泄露
不匹配的使用malloc/new/new[] 和 free/delete/delete[]
重复释放内存
注意: 上面列出的并不很全面,但却包含了能被该工具检测到的很多普遍的问题.
让我们一个一个地对上面的场景进行讨论:
注意: 下面讨论的所有测试代码都应该使用gcc并且加上-g选项(用来在memcheck的输出中生成行号)进行编译. 就想我们之前讨论过的 C程序被编译成可执行文件, 它需要经历四个不同的阶段.
ToB蓝波湾
翻译于 1 年 前
0人顶
顶 翻译的不错哦!
1. 使用未初始化的内存
Code :
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char *p;
char c = *p;
printf("\n [%c]\n",c);
return 0;
}
在上面的代码中,我们尝试使用未初始化的指针 ‘p’.
让我们运行Memcheck来看下结果.
$ valgrind --tool=memcheck ./val
==2862== Memcheck, a memory error detector
==2862== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==2862== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info
==2862== Command: ./val
==2862==
==2862== Use of uninitialised value of size 8
==2862== at 0x400530: main (valgrind.c:8)
==2862==
[#]
==2862==
==2862== HEAP SUMMARY:
==2862== in use at exit: 0 bytes in 0 blocks
==2862== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==2862==
==2862== All heap blocks were freed -- no leaks are possible
==2862==
==2862== For counts of detected and suppressed errors, rerun with: -v
==2862== Use --track-origins=yes to see where uninitialized values come from
==2862== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 4 from 4)
从上面的输出可以看到,Valgrind检测到了未初始化的变量,然后给出了警告(上面加粗的几行(译者注:貌似上面没有加粗的)).
2. 在内存被释放后进行读/写
Code :
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char *p = malloc(1);
*p = 'a';
char c = *p;
printf("\n [%c]\n",c);
free(p);
c = *p;
return 0;
}
上面的代码中,我们有一个释放了内存的指针 ‘p’ 然后我们又尝试利用指针获取值.
让我们运行memcheck来看一下Valgrind对这种情况是如何反应的.
$ valgrind --tool=memcheck ./val
==2849== Memcheck, a memory error detector
==2849== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==2849== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info
==2849== Command: ./val
==2849==
[a]
==2849== Invalid read of size 1
==2849== at 0x400603: main (valgrind.c:30)
==2849== Address 0x51b0040 is 0 bytes inside a block of size 1 free'd
==2849== at 0x4C270BD: free (vg_replace_malloc.c:366)
==2849== by 0x4005FE: main (valgrind.c:29)
==2849==
==2849==
==2849== HEAP SUMMARY:
==2849== in use at exit: 0 bytes in 0 blocks
==2849== total heap usage: 1 allocs, 1 frees, 1 bytes allocated
==2849==
==2849== All heap blocks were freed -- no leaks are possible
==2849==
==2849== For counts of detected and suppressed errors, rerun with: -v
==2849== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 4 from 4)
从上面的输出内容可以看到,Valgrind检测到了无效的读取操作然后输出了警告 ‘Invalid read of size 1′.
另注,使用gdb来调试c程序.
3. 从已分配内存块的尾部进行读/写
Code :
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char *p = malloc(1);
*p = 'a';
char c = *(p+1);
printf("\n [%c]\n",c);
free(p);
return 0;
}
在上面的代码中,我们已经为‘p’分配了一个字节的内存,但我们在将值读取到 ‘c’中的时候使用的是地址p+1.
现在我们使用Valgrind运行上面的代码 :
$ valgrind --tool=memcheck ./val
==2835== Memcheck, a memory error detector
==2835== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==2835== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info
==2835== Command: ./val
==2835==
==2835== Invalid read of size 1
==2835== at 0x4005D9: main (valgrind.c:25)
==2835== Address 0x51b0041 is 0 bytes after a block of size 1 alloc'd
==2835== at 0x4C274A8: malloc (vg_replace_malloc.c:236)
==2835== by 0x4005C5: main (valgrind.c:22)
==2835==
[]
==2835==
==2835== HEAP SUMMARY:
==2835== in use at exit: 0 bytes in 0 blocks
==2835== total heap usage: 1 allocs, 1 frees, 1 bytes allocated
==2835==
==2835== All heap blocks were freed -- no leaks are possible
==2835==
==2835== For counts of detected and suppressed errors, rerun with: -v
==2835== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 4 from 4)
同样,该工具在这种情况下也检测到了无效的读取操作.
4. 内存泄露
Code:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char *p = malloc(1);
*p = 'a';
char c = *p;
printf("\n [%c]\n",c);
return 0;
}
在这次的代码中, 我们申请了一个字节但是没有将它释放.现在让我们运行Valgrind看看会发生什么:
$ valgrind --tool=memcheck --leak-check=full ./val
==2888== Memcheck, a memory error detector
==2888== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==2888== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info
==2888== Command: ./val
==2888==
[a]
==2888==
==2888== HEAP SUMMARY:
==2888== in use at exit: 1 bytes in 1 blocks
==2888== total heap usage: 1 allocs, 0 frees, 1 bytes allocated
==2888==
==2888== 1 bytes in 1 blocks are definitely lost in loss record 1 of 1
==2888== at 0x4C274A8: malloc (vg_replace_malloc.c:236)
==2888== by 0x400575: main (valgrind.c:6)
==2888==
==2888== LEAK SUMMARY:
==2888== definitely lost: 1 bytes in 1 blocks
==2888== indirectly lost: 0 bytes in 0 blocks
==2888== possibly lost: 0 bytes in 0 blocks
==2888== still reachable: 0 bytes in 0 blocks
==2888== suppressed: 0 bytes in 0 blocks
==2888==
==2888== For counts of detected and suppressed errors, rerun with: -v
==2888== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 4 from 4)
输出行(上面加粗的部分)显示,该工具能够检测到内存的泄露.
memcheck工具的使用方式如下:
valgrind --tool=memcheck ./a.out
从上面的命令可以清楚的看到, 主要的命令是valgrind,而我们想使用的工具是通过'-tool'选项来指定的. 上面的‘a.out’指的是我们想使用memcheck运行的可执行文件.
该工具可以检测下列与内存相关的问题 :
未释放内存的使用
对释放后内存的读/写
对已分配内存块尾部的读/写
内存泄露
不匹配的使用malloc/new/new[] 和 free/delete/delete[]
重复释放内存
注意: 上面列出的并不很全面,但却包含了能被该工具检测到的很多普遍的问题.
让我们一个一个地对上面的场景进行讨论:
注意: 下面讨论的所有测试代码都应该使用gcc并且加上-g选项(用来在memcheck的输出中生成行号)进行编译. 就想我们之前讨论过的 C程序被编译成可执行文件, 它需要经历四个不同的阶段.
ToB蓝波湾
翻译于 1 年 前
0人顶
顶 翻译的不错哦!
1. 使用未初始化的内存
Code :
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char *p;
char c = *p;
printf("\n [%c]\n",c);
return 0;
}
在上面的代码中,我们尝试使用未初始化的指针 ‘p’.
让我们运行Memcheck来看下结果.
$ valgrind --tool=memcheck ./val
==2862== Memcheck, a memory error detector
==2862== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==2862== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info
==2862== Command: ./val
==2862==
==2862== Use of uninitialised value of size 8
==2862== at 0x400530: main (valgrind.c:8)
==2862==
[#]
==2862==
==2862== HEAP SUMMARY:
==2862== in use at exit: 0 bytes in 0 blocks
==2862== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==2862==
==2862== All heap blocks were freed -- no leaks are possible
==2862==
==2862== For counts of detected and suppressed errors, rerun with: -v
==2862== Use --track-origins=yes to see where uninitialized values come from
==2862== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 4 from 4)
从上面的输出可以看到,Valgrind检测到了未初始化的变量,然后给出了警告(上面加粗的几行(译者注:貌似上面没有加粗的)).
2. 在内存被释放后进行读/写
Code :
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char *p = malloc(1);
*p = 'a';
char c = *p;
printf("\n [%c]\n",c);
free(p);
c = *p;
return 0;
}
上面的代码中,我们有一个释放了内存的指针 ‘p’ 然后我们又尝试利用指针获取值.
让我们运行memcheck来看一下Valgrind对这种情况是如何反应的.
$ valgrind --tool=memcheck ./val
==2849== Memcheck, a memory error detector
==2849== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==2849== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info
==2849== Command: ./val
==2849==
[a]
==2849== Invalid read of size 1
==2849== at 0x400603: main (valgrind.c:30)
==2849== Address 0x51b0040 is 0 bytes inside a block of size 1 free'd
==2849== at 0x4C270BD: free (vg_replace_malloc.c:366)
==2849== by 0x4005FE: main (valgrind.c:29)
==2849==
==2849==
==2849== HEAP SUMMARY:
==2849== in use at exit: 0 bytes in 0 blocks
==2849== total heap usage: 1 allocs, 1 frees, 1 bytes allocated
==2849==
==2849== All heap blocks were freed -- no leaks are possible
==2849==
==2849== For counts of detected and suppressed errors, rerun with: -v
==2849== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 4 from 4)
从上面的输出内容可以看到,Valgrind检测到了无效的读取操作然后输出了警告 ‘Invalid read of size 1′.
另注,使用gdb来调试c程序.
3. 从已分配内存块的尾部进行读/写
Code :
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char *p = malloc(1);
*p = 'a';
char c = *(p+1);
printf("\n [%c]\n",c);
free(p);
return 0;
}
在上面的代码中,我们已经为‘p’分配了一个字节的内存,但我们在将值读取到 ‘c’中的时候使用的是地址p+1.
现在我们使用Valgrind运行上面的代码 :
$ valgrind --tool=memcheck ./val
==2835== Memcheck, a memory error detector
==2835== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==2835== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info
==2835== Command: ./val
==2835==
==2835== Invalid read of size 1
==2835== at 0x4005D9: main (valgrind.c:25)
==2835== Address 0x51b0041 is 0 bytes after a block of size 1 alloc'd
==2835== at 0x4C274A8: malloc (vg_replace_malloc.c:236)
==2835== by 0x4005C5: main (valgrind.c:22)
==2835==
[]
==2835==
==2835== HEAP SUMMARY:
==2835== in use at exit: 0 bytes in 0 blocks
==2835== total heap usage: 1 allocs, 1 frees, 1 bytes allocated
==2835==
==2835== All heap blocks were freed -- no leaks are possible
==2835==
==2835== For counts of detected and suppressed errors, rerun with: -v
==2835== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 4 from 4)
同样,该工具在这种情况下也检测到了无效的读取操作.
4. 内存泄露
Code:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char *p = malloc(1);
*p = 'a';
char c = *p;
printf("\n [%c]\n",c);
return 0;
}
在这次的代码中, 我们申请了一个字节但是没有将它释放.现在让我们运行Valgrind看看会发生什么:
$ valgrind --tool=memcheck --leak-check=full ./val
==2888== Memcheck, a memory error detector
==2888== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==2888== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info
==2888== Command: ./val
==2888==
[a]
==2888==
==2888== HEAP SUMMARY:
==2888== in use at exit: 1 bytes in 1 blocks
==2888== total heap usage: 1 allocs, 0 frees, 1 bytes allocated
==2888==
==2888== 1 bytes in 1 blocks are definitely lost in loss record 1 of 1
==2888== at 0x4C274A8: malloc (vg_replace_malloc.c:236)
==2888== by 0x400575: main (valgrind.c:6)
==2888==
==2888== LEAK SUMMARY:
==2888== definitely lost: 1 bytes in 1 blocks
==2888== indirectly lost: 0 bytes in 0 blocks
==2888== possibly lost: 0 bytes in 0 blocks
==2888== still reachable: 0 bytes in 0 blocks
==2888== suppressed: 0 bytes in 0 blocks
==2888==
==2888== For counts of detected and suppressed errors, rerun with: -v
==2888== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 4 from 4)
输出行(上面加粗的部分)显示,该工具能够检测到内存的泄露.
推荐于2016-07-30
展开全部
有点繁琐,~~希望一次成功哦~~。
# cd linux-2.6.24 (进入到/usr/src/linux-2.6.18目录下)
# make mrproper (该命令可确保源代码目录下没有不正确的.o文件)
# make menuconfig (配置内核各选项)
此时会出现一个图形界面,列出了所有的内核配置选项,有的选项下还有子选项,你可以用方向键来选择,用Y键来确定。经过我多次试验,大多数选项默认就行,以下几个选项必须选择(请认真核对下面每一个选项,否则编译很有可能前功尽弃):
(1)Loadable Module support选项中,选上“Module unloading”和“Automatic kernel module loading”这两项;
(2)Device Drivers--->Block Devices中选上“Loopback device support”;
Device Drivers--->Multi-device support(RAID and LVM)处要选上“device mapper support”;
Device Drivers--->Graphics support,一定要选上“ Support for frame buffer devices”;
Device Drivers --->USB support --->选上“USB Mass Storage support”(如果是在实环境中,想要更多USB支持,就全选吧。我的是在虚拟机中,用不着了)
Device Drivers --->;Network device support --->Ethernet (10 or 100Mbit) ---><*> AMD PCnet32 PCI support
(3)File system--->(以下9个选项是关于ext2和ext3文件系统配置,全部选上)
Second extended fs support
Ext2 extended attributes
Ext2 POSIX Access Control Lists
Ext2 Security Labels
Ext3 journalling file system support
Ext3 extended attributes
Ext3 POSIX Access Control Lists
Ext3 Security Labels
JBB (ext3) debugging support
File system--->DOS/FAT/NT Filesystems --->选上“NTFS file system support”;
# cd linux-2.6.24 (进入到/usr/src/linux-2.6.18目录下)
# make mrproper (该命令可确保源代码目录下没有不正确的.o文件)
# make menuconfig (配置内核各选项)
此时会出现一个图形界面,列出了所有的内核配置选项,有的选项下还有子选项,你可以用方向键来选择,用Y键来确定。经过我多次试验,大多数选项默认就行,以下几个选项必须选择(请认真核对下面每一个选项,否则编译很有可能前功尽弃):
(1)Loadable Module support选项中,选上“Module unloading”和“Automatic kernel module loading”这两项;
(2)Device Drivers--->Block Devices中选上“Loopback device support”;
Device Drivers--->Multi-device support(RAID and LVM)处要选上“device mapper support”;
Device Drivers--->Graphics support,一定要选上“ Support for frame buffer devices”;
Device Drivers --->USB support --->选上“USB Mass Storage support”(如果是在实环境中,想要更多USB支持,就全选吧。我的是在虚拟机中,用不着了)
Device Drivers --->;Network device support --->Ethernet (10 or 100Mbit) ---><*> AMD PCnet32 PCI support
(3)File system--->(以下9个选项是关于ext2和ext3文件系统配置,全部选上)
Second extended fs support
Ext2 extended attributes
Ext2 POSIX Access Control Lists
Ext2 Security Labels
Ext3 journalling file system support
Ext3 extended attributes
Ext3 POSIX Access Control Lists
Ext3 Security Labels
JBB (ext3) debugging support
File system--->DOS/FAT/NT Filesystems --->选上“NTFS file system support”;
本回答被提问者和网友采纳
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询