2010-04-10 6 views
132

Also habe ich einige mysteriöse nicht initialisierte Werte von Valgrind bekommen und es war ziemlich das Mysterium, woher der schlechte Wert kam."konditionaler Sprung oder Bewegung hängt von nicht initialisierten Werten ab" valgrind message

Scheint, dass Valgrind den Ort zeigt, an dem der unitialisierte Wert verwendet wird, aber nicht den Ursprung des nicht initialisierten Wertes.

==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 man sehen kann, ist es durchaus kryptischen wird .. vor allem, weil, wenn es von der Klasse sagen ist :: MethodX, ist es manchmal gerade Punkte usw. bis oStream Vielleicht ist dies eine Optimierung durch?

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

Einfach so. Gibt es etwas, das mir fehlt? Was ist der beste Weg, um schlechte Werte zu erfassen, ohne auf super-printf Detektivarbeit zurückgreifen zu müssen?

Update:

ich herausgefunden habe, was falsch war, aber das Merkwürdige ist, valgrind hat es nicht berichten, wenn der schlechte Wert zum ersten Mal verwendet wurde. Es wurde in einer Multiplikationsfunktion verwendet:

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

Wo Speedfac eine unitialisierte Float war. Zu diesem Zeitpunkt wurde es jedoch nicht gemeldet, und erst wenn der Wert gedruckt wird, erhalte ich den Fehler. Gibt es eine Einstellung für Valgrind, um dieses Verhalten zu ändern?

Antwort

191

Verwenden Sie die Valgrind-Option --track-origins=yes, um den Ursprung nicht initialisierter Werte nachzuverfolgen. Dadurch wird es langsamer und benötigt mehr Speicher. Dies kann jedoch sehr hilfreich sein, wenn Sie den Ursprung eines nicht initialisierten Werts ermitteln müssen.

Update: In Bezug auf den Punkt, an dem der nicht initialisierten Wert gemeldet wird, the valgrind manual states:

Es ist wichtig, dass Ihr Programm zu verstehen, um Junk (uninitialised) Daten, so viel kopieren können, wie es mag. Memcheck beobachtet dies und behält die Daten im Auge, beschweren sich aber nicht. Eine Beschwerde wird nur ausgegeben, wenn Ihr Programm versucht, nicht initialisierte Daten so zu verwenden, dass das extern sichtbare Verhalten Ihres Programms beeinträchtigt wird.

Vom Valgrind FAQ:

Was eifrig Meldung von Kopien von uninitialised Speicherwerten, dies wurde mehrfach vorgeschlagen. Leider kopieren fast alle Programme legitimerweise nicht initialisierte Speicherwerte (da Compiler Padstrukturen zum Beibehalten der Ausrichtung beibehalten) und eifrige Überprüfung führt zu Hunderten von Fehlalarmen. Daher unterstützt Memche derzeit keine eifrige Überprüfung.

+1

Was ist die minimale valgrind Version, um diese Funktion zu benutzen? Ich benutze 3.3.0 und es scheint die Option nicht zu mögen. –

+6

@Robert: --track-origins wurde in valgrind 3.4.0 hinzugefügt – mark4o

16

Dies bedeutet, dass Sie versuchen, einen Wert auszugeben/auszugeben, der zumindest teilweise nicht initialisiert ist. Können Sie es eingrenzen, so dass Sie genau wissen, welcher Wert das ist? Verfolgen Sie anschließend Ihren Code, um zu sehen, wo er initialisiert wird. Wahrscheinlich werden Sie sehen, dass es nicht vollständig initialisiert wird.

Wenn Sie weitere Hilfe benötigen, können Sie die entsprechenden Abschnitte des Quellcodes veröffentlichen, damit jemand mehr Anleitungen geben kann.

EDIT

Ich sehe das Problem gefunden haben. Beachten Sie, dass Valgrind Uhren für bedingten Sprung oder auf der Grundlage von unitären Variablen überwacht. Dies bedeutet, dass es nur dann eine Warnung ausgibt, wenn die Ausführung des Programms aufgrund des nicht initialisierten Werts geändert wird (dh das Programm nimmt beispielsweise einen anderen Zweig in einer if-Anweisung). Da die eigentliche Arithmetik keinen bedingten Sprung oder eine bedingte Bewegung beinhaltete, warnte Valgrind Sie nicht davor. Stattdessen hat es den Status "nicht initialisiert" an das Ergebnis der Anweisung weitergegeben, die es verwendet hat.

Es kann nicht eingängig scheint, dass es nicht, dass Sie sofort warnt, sondern als mark4o wies darauf hin, es tut dies, weil nicht initialisierte Werte in C die ganze Zeit (Beispiele gewöhnen: Polsterung in Strukturen, die realloc() Anruf usw.) Diese Warnungen wären aufgrund der falsch positiven Frequenz nicht sehr nützlich.

+0

Danke. Ich habe gerade herausgefunden, was falsch war, aber das Seltsame ist, dass Valgrind das unitialisierte Wertobjekt erst gemeldet hat, als es an anderer Stelle verwendet wurde. – kamziro

+0

Das ist beabsichtigt. Wenn nur das Kopieren oder Weiterleiten von nicht initialisierten Werten zu einem Fehlerbericht führte, würden Sie sie immer wieder vom Auffüllen in Strukturen erhalten. – mark4o