如何有效使用Valgrind

5

我刚开始学习使用valgrind和--tool=memcheck。

但我遇到的问题是找出实际存在的问题。

例如:

其中一个问题是这样的。

==12561== Conditional jump or move depends on uninitialised value(s)
==12561==    at 0x425779: Server::HandleReceiveFrom(boost::system::error_code const&, unsigned long) (mUUID.h:63)
==12561==    by 0x428EC4: boost::asio::detail::reactive_socket_recvfrom_op<boost::asio::mutable_buffers_1, boost::asio::ip::basic_endpoint<boost::asio::ip::udp>, boost::_bi::bind_t<void, boost::_mfi::mf2<void, Server, boost::system::error_code const&, unsigned long>, boost::_bi::list3<boost::_bi::value<Server*>, boost::arg<1> (*)(), boost::arg<2> (*)()> > >::do_complete(boost::asio::detail::task_io_service*, boost::asio::detail::task_io_service_operation*, boost::system::error_code, unsigned long) (mem_fn_template.hpp:280)
==12561==    by 0x42E589: boost::asio::detail::task_io_service::run(boost::system::error_code&) (task_io_service_operation.hpp:35)
==12561==    by 0x42720C: Server::Run() (io_service.ipp:57)
==12561==    by 0x42FB00: main (obbs.cpp:198)

还有一个是这个

== Use of uninitialised value of size 8
==12561==    at 0x5E56091: _itoa_word (_itoa.c:196)
==12561==    by 0x5E573D8: vfprintf (vfprintf.c:1613)
==12561==    by 0x5F0EA6F: __vsnprintf_chk (vsnprintf_chk.c:65)

我需要一些关于如何最有效地跟踪这些问题的提示。(条件跳转和未初始化的值。)

编辑

这是什么需要担心的吗?似乎通过选项--run-libc-freeres=no消失了。 这是否意味着我的C库有漏洞?

==14754== Invalid free() / delete / delete[]
==14754==    at 0x4C27D71: free (vg_replace_malloc.c:366)
==14754==    by 0x5F43A0A: free_mem (in /lib/libc-2.12.1.so)
==14754==    by 0x5F435A1: __libc_freeres (in /lib/libc-2.12.1.so)
==14754==    by 0x4A2366B: _vgnU_freeres (vg_preloaded.c:62)
==14754==    by 0x5E4A4A4: exit (exit.c:93)
==14754==    by 0x5E2FD94: (below main) (libc-start.c:258)
==14754==  Address 0x4046bb8 is not stack'd, malloc'd or (recently) free'd

+1 是一个非常重要的工具,能够使用它是必不可少的。 - jk.
未初始化的值在Valgrind的QuickStart中有详细解释。该文档总共包含大约12段内容,其中关于未初始化的值的部分较少。 - isomorphismes
1个回答

15

基本上,每个Valgrind错误都会显示一个堆栈跟踪。堆栈跟踪的较高部分可能对您没有太大用处,因为它们是指向库代码的。然而,这些问题最终源于您的代码问题。首先扫描堆栈跟踪的第一部分,它是指向您应用程序中的代码行(而不是库函数)。如果您检查堆栈跟踪,您会发现obbs.cpp的198行是导致您第一个问题的原因所在。在跟踪栈的更高位置,您可以看到mUUID.h的63行最终评估了未初始化的变量,无论是通过if语句还是循环。

"Conditional jump or move depends on uninitialised value(s)"这个错误意味着您有一个未初始化的变量正在用于影响程序流程。在您的情况下,看起来您正在将一个未初始化的变量传递给Boost库函数,库函数调用了您的处理程序类,并在条件语句中评估未初始化的变量。这意味着您的程序正在显示未定义的行为。

一个简单的示例,可能导致此问题的产生,就像:

int i; // uninitialized value
if (i == 10) { /* ... do something */ }

从检查obbs.cpp的第198行开始,并沿着堆栈跟踪向上移动,直到你意识到问题。

我还要补充的是,这样的错误有时可以被编译器捕获,如果你编译时开启所有警告。(例如,在GCC中,请确保使用-Wall标志进行编译)


1
谢谢你的提示。Valgrind有时会出错吗?我看不到任何未初始化的变量。那么延迟初始化呢? - hookenz
3
Valgrind 几乎不会报告错误阳性结果。 - Charles Salvia
尝试查看堆栈跟踪更高的位置,例如在 mUUID.h 的第63行,那里调用了您的回调处理程序。您的处理程序类的所有成员变量是否都已初始化? - Charles Salvia
基本上是真的。虽然我上面提到的C库不是误报,但这是C库中存在的问题。 - hookenz
感谢您的回答。我找到了问题所在。原来是mUUID的堆栈损坏问题。只需要一个字节就可以解决。 - hookenz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接