用Valgrind查找无效指针使用
用memcheck工具,Valgrind也可以找出无效堆内存使用。比如,如果你用malloc或new分配了一个数组,并访问数组末端后面的内存:
char *x = malloc(10);
x[10] = ′a′;
Valgrind可以检测出这个错误。用Valgrind运行下面的示例程序:example2
#include
int main()
{
char *x = malloc(10);
x[10] = ′a′;
return 0;
}
%valgrind --tool=memcheck --leak-check=yes example2
其结果是(片断)
==9814== Invalid write of size 1
==9814== at 0x804841E: main (tst.c:6)
==9814== Address 0x1BA3607A is 0 bytes after a block of size 10 alloc′d
==9814== at 0x1B900DD0: malloc (vg_replace_malloc.c:131)
==9814== by 0x804840F: main (example2.c:5)
这个信息表明我们分配了10字节的内存,但是访问了超出范围的内存,因此,我们就进行了一个′非法写′操作。如果试图从那块内存读取数据,我们就会得到 ′Invalid read of size X′的警告(X是试图读取数据的大小,char是一个字节,而int根据系统的不同可能是2个字节或4个字节)。通常,Valgrind显示出函数调用栈信息以方便我们准确定位错误。
检测使用未初始化变量
还有一类Valgrind可以检测的操作是在条件判断语句中使用未初始化变量。也许你应该养成在声明变量时就进行初始化的习惯,不过Valgrind仍然可以帮助你找出使用未初始化变量的地方。比如,运行下面代码生成的示例程序,example3
#include
int main()
{
int x;
if(x == 0)
{
printf("X is zero"); /* replace with cout and include
iostream for C++ */
}
return 0;
}
Valgrind会给出下面的结果(片断)
==17943== Conditional jump or move depends on uninitialised value(s)
==17943== at 0x804840A: main (example3.c:6)
Valgrind甚至可以知道如果一个变量被赋予一个未初始化的变量,这个变量仍然处于"未初始化"状态。比如运行下列代码:
#include
int foo(int x)
{
if(x < 10)
{
printf("x is less than 10\n");
}
}
int main()
{
int y;
foo(y);
}
Valgrind会给出下列警告:
==4827== Conditional jump or move depends on uninitialised value(s)
==4827== at 0x8048366: foo (example4.c:5)
==4827== by 0x8048394: main (example4.c:14)
你可能以为错误在foo中,和调用栈上的其它函数没有关系。但是因为main函数传递了一个未初始化值给foo,我们可以根据调用栈信息顺藤摸瓜,找到真正没有初始化变量的代码。
Valgrind仅仅有助于你在能够运行到代码中检测这些错误,请确信在测试中覆盖代码的每一个分支。
本文介绍如何使用Valgrind的memcheck工具检测C/C++程序中的内存错误,包括越界访问和使用未初始化变量等问题,并通过示例展示Valgrind如何帮助定位这些问题。
2025

被折叠的 条评论
为什么被折叠?



