所以我一直在从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)
Run Code Online (Sandbox Code Playgroud)
可以看出,它变得非常神秘......特别是因为当它由Class :: MethodX说时,它有时直接指向ostream等.也许这是由于优化?
==11366== by 0x81109ED: Snake::SnakeBody::syncBodyPos() (ostream:221)
Run Code Online (Sandbox Code Playgroud)
就像那样.有什么我想念的吗?在不必诉诸超长印刷侦探工作的情况下,捕捉坏价值的最佳方法是什么?
更新:
我发现了什么是错的,但奇怪的是,当首次使用坏值时,valgrind没有报告.它用于乘法函数:
movespeed = stat.speedfactor * speedfac * currentbendfactor.val;
Run Code Online (Sandbox Code Playgroud)
speedfac是一个单一化的浮子.但是,当时没有报告,直到打印出来的值我才得到错误.是否有一个valgrind设置来改变这种行为?
mar*_*k4o 225
使用valgrind选项--track-origins=yes可以跟踪未初始化值的来源.这将使速度变慢并占用更多内存,但如果您需要追踪未初始化值的来源,则可能会非常有用.
更新:关于报告未初始化值的点,valgrind手册指出:
重要的是要了解您的程序可以根据需要复制垃圾(未初始化)数据.Memcheck观察到这一点并跟踪数据,但不抱怨.只有当您的程序试图以可能影响程序外部可见行为的方式使用未初始化数据时,才会发出投诉.
来自Valgrind FAQ:
至于急切报告未初始化的内存值的副本,已经多次提出这一点.不幸的是,几乎所有程序都合法地复制未初始化的内存值(因为编译器填充结构以保持对齐)和急切检查会导致数百个误报.因此,Memcheck目前不支持急切检查.
Rar*_*arr 20
这意味着您正在尝试打印/输出至少部分未初始化的值.你能缩小范围,以便确切知道它的价值是多少?之后,跟踪代码以查看它的初始化位置.有可能,你会发现它没有被完全初始化.
如果您需要更多帮助,发布源代码的相关部分可能允许某人提供更多指导.
编辑
我发现你发现了问题.请注意,valgrind 监视条件跳转或基于单位化变量移动.这意味着,如果由于未初始化的值而改变了程序的执行,它将仅发出警告(例如,程序在if语句中采用不同的分支).由于实际算术不涉及条件跳转或移动,因此valgrind没有警告你.相反,它将"未初始化"状态传播到使用它的语句的结果.
它似乎没有立即警告你,但正如mark4o指出的那样,它是这样做的,因为未初始化的值一直在C中使用(例如:结构中的填充,realloc()调用等)所以那些警告不会是由于误报率非常有用.