Ich habe also eine mysteriöse Nachricht über nicht initialisierte Werte von Valgrind erhalten, und es war ziemlich rätselhaft, woher der schlechte Wert stammt.
Scheint, dass valgrind den Ort anzeigt, an dem der unitialisierte Wert verwendet wird, aber nicht den Ursprung des nicht initialisierten Werts.
==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)
Wie zu sehen ist, wird es ziemlich kryptisch. Besonders, wenn es von Class :: MethodX gesagt wird, zeigt es manchmal direkt auf ostream usw. Vielleicht liegt das an der Optimierung?
==11366== by 0x81109ED: Snake::SnakeBody::syncBodyPos() (ostream:221)
Genau so. Fehlt mir etwas? Was ist der beste Weg, um schlechte Werte zu erfassen, ohne auf superlange Detektivarbeit zurückgreifen zu müssen?
Aktualisieren:
Ich fand heraus, was los war, aber das Seltsame ist, dass Valgrind es nicht gemeldet hat, als der schlechte Wert zum ersten Mal verwendet wurde. Es wurde in einer Multiplikationsfunktion verwendet:
movespeed = stat.speedfactor * speedfac * currentbendfactor.val;
Wo Speedfac ein unitialisierter Schwimmer war. Zu diesem Zeitpunkt wurde jedoch nicht gemeldet, und erst wenn der Wert gedruckt werden soll, wird der Fehler angezeigt. Gibt es eine Einstellung für valgrind, um dieses Verhalten zu ändern?
Dies bedeutet, dass Sie versuchen, einen Wert auszudrucken / auszugeben, der zumindest teilweise nicht initialisiert ist. Können Sie es eingrenzen, damit Sie genau wissen, welcher Wert das ist? Verfolgen Sie anschließend Ihren Code, um zu sehen, wo er initialisiert wird. Möglicherweise werden Sie feststellen, dass es nicht vollständig initialisiert wird.
Wenn Sie weitere Hilfe benötigen, kann das Posten der relevanten Abschnitte des Quellcodes es jemandem ermöglichen, weitere Anleitungen anzubieten.
BEARBEITEN
Ich sehe, Sie haben das Problem gefunden. Beachten Sie, dass valgrind basierend auf einheitlichen Variablen auf bedingte Sprünge oder Bewegungen achtet. Dies bedeutet, dass nur dann eine Warnung ausgegeben wird, wenn die Ausführung des Programms aufgrund des nicht initialisierten Werts geändert wird (dh das Programm nimmt beispielsweise in einer if-Anweisung einen anderen Zweig). Da die eigentliche Arithmetik keinen bedingten Sprung oder eine bedingte Bewegung beinhaltete, warnte Valgrind Sie nicht davor. Stattdessen wurde der Status "nicht initialisiert" an das Ergebnis der Anweisung weitergegeben, die ihn verwendet hat.
Es mag nicht intuitiv erscheinen, Sie nicht sofort zu warnen, aber wie mark4o hervorhob , geschieht dies, weil in C ständig nicht initialisierte Werte verwendet werden (Beispiele: Auffüllen von Strukturen,
realloc()
Aufruf usw.), sodass diese Warnungen nicht angezeigt werden sehr nützlich wegen der falsch positiven Frequenz.quelle