对象内的 Valgrind 数组溢出
Valgrind array overrun within objects
我有一个简单的程序如下。
struct Test
{
int a[5];
int b;
};
int main()
{
Test* t = new Test;
t->b = 1;
t->a[5] = 5; //This is an illegal write
cout << t->b << endl; //Output is 5
return 0;
}
运行它与Valgrind Memcheck 没有报告非法内存写入。
我注意到 Valgrind 声称 Memcheck 工具无法检测全局或堆栈数组溢出,但这个数组在堆中,对吗?只是数组在一个对象中。
是Valgrind真的检测不到这种错误还是我做错了什么?如果前者为真,那么是否有任何其他工具可以检测此类错误?
=========================================== =============================
更新:
我使用的编译命令是g++ -O0 -g main.cc
。 valgrind
命令只是 valgrind ./a.out
,它应该默认调用 memcheck
工具。
编译器版本为gcc version 4.4.7 20120313 (Red Hat 4.4.7-4) (GCC)
,valgrind
版本为valgrind-3.5.0
。
当 运行 这个程序时 Valgrind 输出:
==7759== Memcheck, a memory error detector
==7759== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==7759== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info
==7759== Command: ./a.out
==7759==
5
==7759==
==7759== HEAP SUMMARY:
==7759== in use at exit: 24 bytes in 1 blocks
==7759== total heap usage: 1 allocs, 0 frees, 24 bytes allocated
==7759==
==7759== LEAK SUMMARY:
==7759== definitely lost: 24 bytes in 1 blocks
==7759== indirectly lost: 0 bytes in 0 blocks
==7759== possibly lost: 0 bytes in 0 blocks
==7759== still reachable: 0 bytes in 0 blocks
==7759== suppressed: 0 bytes in 0 blocks
==7759== Rerun with --leak-check=full to see details of leaked memory
==7759==
==7759== For counts of detected and suppressed errors, rerun with: -v
==7759== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 4 from 4)
我认为下面这句话你已经找到了:
Memcheck cannot detect every memory error your program has. For
example, it can't detect out-of-range reads or writes to arrays that
are allocated statically or on the stack. But it should detect many
errors that could crash your program (eg. cause a segmentation fault).
如果您的 class 定义应该这样解释:
虽然class对象是动态分配的,但数组本身是静态分配的。
我验证过几个案例:
如果数组是动态分配的,Valgrind 将报告无效写入:
struct Test
{
int *a;
int b;
};
int main()
{
Test* t = new Test;
t->a = new int[5];
t->b = 1;
t->a[5] = 5; //This is an illegal write
cout << t->b << endl; //Output is 5
delete [] t->a;
delete t;
return 0;
}
成员顺序改为:
也会报错
struct Test
{
int b;
int a[5];
};
这是因为在尝试写入 [5] 时,我们已经落后于动态分配的对象。
使用原始 class 定义,如果您尝试写入 [6] - 因为那样我们落后于 b
,所以落后于动态分配的对象。
更新:gcc sanitizer(我也怀疑 clang)通过编译在 运行 时检测到此越界访问:
g++ -fno-omit-frame-pointer -fsanitize=bounds m.cpp
输出:
m.cpp:15:7: runtime error: index 5 out of bounds for type 'int [5]'
我有一个简单的程序如下。
struct Test
{
int a[5];
int b;
};
int main()
{
Test* t = new Test;
t->b = 1;
t->a[5] = 5; //This is an illegal write
cout << t->b << endl; //Output is 5
return 0;
}
运行它与Valgrind Memcheck 没有报告非法内存写入。
我注意到 Valgrind 声称 Memcheck 工具无法检测全局或堆栈数组溢出,但这个数组在堆中,对吗?只是数组在一个对象中。
是Valgrind真的检测不到这种错误还是我做错了什么?如果前者为真,那么是否有任何其他工具可以检测此类错误?
=========================================== =============================
更新:
我使用的编译命令是g++ -O0 -g main.cc
。 valgrind
命令只是 valgrind ./a.out
,它应该默认调用 memcheck
工具。
编译器版本为gcc version 4.4.7 20120313 (Red Hat 4.4.7-4) (GCC)
,valgrind
版本为valgrind-3.5.0
。
当 运行 这个程序时 Valgrind 输出:
==7759== Memcheck, a memory error detector
==7759== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==7759== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info
==7759== Command: ./a.out
==7759==
5
==7759==
==7759== HEAP SUMMARY:
==7759== in use at exit: 24 bytes in 1 blocks
==7759== total heap usage: 1 allocs, 0 frees, 24 bytes allocated
==7759==
==7759== LEAK SUMMARY:
==7759== definitely lost: 24 bytes in 1 blocks
==7759== indirectly lost: 0 bytes in 0 blocks
==7759== possibly lost: 0 bytes in 0 blocks
==7759== still reachable: 0 bytes in 0 blocks
==7759== suppressed: 0 bytes in 0 blocks
==7759== Rerun with --leak-check=full to see details of leaked memory
==7759==
==7759== For counts of detected and suppressed errors, rerun with: -v
==7759== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 4 from 4)
我认为下面这句话你已经找到了:
Memcheck cannot detect every memory error your program has. For example, it can't detect out-of-range reads or writes to arrays that are allocated statically or on the stack. But it should detect many errors that could crash your program (eg. cause a segmentation fault).
如果您的 class 定义应该这样解释: 虽然class对象是动态分配的,但数组本身是静态分配的。
我验证过几个案例:
如果数组是动态分配的,Valgrind 将报告无效写入:
struct Test
{
int *a;
int b;
};
int main()
{
Test* t = new Test;
t->a = new int[5];
t->b = 1;
t->a[5] = 5; //This is an illegal write
cout << t->b << endl; //Output is 5
delete [] t->a;
delete t;
return 0;
}
成员顺序改为:
也会报错struct Test
{
int b;
int a[5];
};
这是因为在尝试写入 [5] 时,我们已经落后于动态分配的对象。
使用原始 class 定义,如果您尝试写入 [6] - 因为那样我们落后于 b
,所以落后于动态分配的对象。
更新:gcc sanitizer(我也怀疑 clang)通过编译在 运行 时检测到此越界访问:
g++ -fno-omit-frame-pointer -fsanitize=bounds m.cpp
输出:
m.cpp:15:7: runtime error: index 5 out of bounds for type 'int [5]'