c++ - valgrind教程 - valgrind是什么




精确定位“有条件跳转或移动取决于未初始化的值”(valgrind消息) (2)

使用valgrind选项--track-origins=yes可以跟踪未初始化值的来源。 这会让它变慢并占用更多内存,但是如果您需要追踪未初始化值的来源,它会非常有帮助。

更新:关于未初始化值的报告点, valgrind手册指出

理解您的程序可以尽可能复制垃圾(未初始化)的数据,这一点很重要。 Memcheck注意到这一点,并跟踪数据,但不抱怨。 只有当您的程序尝试以可能影响程序外部可见行为的方式使用未初始化的数据时才会发出投诉。

来自Valgrind常见问题解答

至于渴望报告未初始化的内存值的副本,这已被多次提出。 不幸的是,几乎所有的程序都合法地复制了未初始化的内存值(因为编译器会修改结构以保持对齐),并且急切的检查会导致数百个误报。 因此,Memcheck目前不支持急切检查。

所以我一直在从Valgrind那里得到一些神秘的未初始化值的消息,而且这个坏的价值源于哪里一直是个谜。

似乎valgrind显示单位化值最终被使用的地方,但不是未初始化值的来源。

==11366== Conditional jump or move depends on uninitialised value(s)
==11366==    at 0x43CAE4F: __printf_fp (in /lib/tls/i686/cmov/libc-2.7.so)
==11366==    by 0x43C6563: vfprintf (in /lib/tls/i686/cmov/libc-2.7.so)
==11366==    by 0x43EAC03: vsnprintf (in /lib/tls/i686/cmov/libc-2.7.so)
==11366==    by 0x42D475B: (within /usr/lib/libstdc++.so.6.0.9)
==11366==    by 0x42E2C9B: std::ostreambuf_iterator<char, std::char_traits<char> > std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::_M_insert_float<double>(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, char, double) const (in /usr/lib/libstdc++.so.6.0.9)
==11366==    by 0x42E31B4: std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::do_put(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, double) const (in /usr/lib/libstdc++.so.6.0.9)
==11366==    by 0x42EE56F: std::ostream& std::ostream::_M_insert<double>(double) (in /usr/lib/libstdc++.so.6.0.9)
==11366==    by 0x81109ED: Snake::SnakeBody::syncBodyPos() (ostream:221)
==11366==    by 0x810B9F1: Snake::Snake::update() (snake.cpp:257)
==11366==    by 0x81113C1: SnakeApp::updateState() (snakeapp.cpp:224)
==11366==    by 0x8120351: RoenGL::updateState() (roengl.cpp:1180)
==11366==    by 0x81E87D9: Roensachs::update() (rs.cpp:321)

可以看出,它变得相当神秘......尤其是因为当它通过Class :: MethodX说话时,它有时直接指向ostream等。这可能是由于优化?

==11366==    by 0x81109ED: Snake::SnakeBody::syncBodyPos() (ostream:221)

就这样。 有什么我失踪? 在不必诉诸超长的printf侦查工作的情况下,抓住不良价值的最佳方式是什么?

更新:

我发现哪里出了什么问题,但奇怪的是,valgrind在第一次使用坏值时没有报告。 它被用在乘法函数中:

movespeed = stat.speedfactor * speedfac * currentbendfactor.val;

speedfac是一个单位浮点数。 然而,那时它没有被报告,直到要打印的值才得到错误。是否有valgrind改变这种行为的设置?


这意味着你正试图打印输出一个至少部分未初始化的值。 你能缩小它,以便你确切知道那是什么价值吗? 之后,通过您的代码追踪它的初始化位置。 机会是,你会看到它没有被完全初始化。

如果您需要更多帮助,发布源代码的相关部分可能会允许某人提供更多指导。

编辑

我发现你发现了这个问题。 请注意,valgrind监视条件跳转或基于单位变量移动 。 这意味着如果程序的执行由于未初始化的值而改变(例如程序在if语句中采用不同的分支),它将只会发出警告。 由于实际算术不涉及有条件的跳跃或移动,因此valgrind并未警告您。 相反,它会将“未初始化”状态传播到使用它的语句的结果。

它似乎并不直接警告你,但正如mark4o指出的那样,它是这样做的,因为未初始化的值始终在C中使用(例如:结构中的padding, realloc()调用等),所以这些警告由于误报频率而不会非常有用。