2010-04-10 10 views
132

Quindi ho ricevuto alcuni misteriosi messaggi di valori non inizializzati da valgrind ed è stato piuttosto il mistero da dove proveniva il valore errato.localizzare "il salto condizionale o lo spostamento dipende dal/i valore/i non inizializzato/i" valgrind messaggio

Sembra che valgrind mostri il luogo in cui viene utilizzato il valore unitializzato, ma non l'origine del valore non inizializzato.

==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) 

Come si può vedere, si fa piuttosto criptico .. soprattutto perché quando si sta dicendo da Class :: MethodX, a volte punta dritto al ostream ecc Forse questo è dovuto all'ottimizzazione?

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

Proprio così. C'è qualcosa che mi manca? Qual è il modo migliore per ottenere cattivi valori senza dover ricorrere a un lavoro investigativo di lunghissima stampa?

Aggiornamento:

ho scoperto cosa era sbagliato, ma la cosa strana è, valgrind non segnalarlo quando il valore di cattivo è stato utilizzato prima. È stato utilizzato in una funzione di moltiplicazione:

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

Dove speedfac era un galleggiante unitializzato. Tuttavia, in quel momento non è stato segnalato e non fino a quando il valore deve essere stampato che ottengo l'errore .. Esiste un'impostazione per valgrind per modificare questo comportamento?

risposta

191

Utilizzare l'opzione valgrind --track-origins=yes per fare in modo che tenga traccia dell'origine dei valori non inizializzati. Ciò lo renderà più lento e richiederà più memoria, ma può essere molto utile se devi rintracciare l'origine di un valore non inizializzato.

Aggiornamento: Per quanto riguarda il punto in cui è riportato il valore non inizializzato, the valgrind manual states:

E 'importante capire che il programma può copiare i dati spazzatura in giro (non inizializzate) tanto quanto lo ama. Memcheck osserva questo e tiene traccia dei dati, ma non si lamenta. Un reclamo viene emesso solo quando il tuo programma tenta di utilizzare i dati non inizializzati in un modo che potrebbe influire sul comportamento esternamente visibile del programma.

Dal Valgrind FAQ:

Per quanto riguarda la segnalazione desiderosi di copie di valori di memoria non inizializzate, questo è stato suggerito più volte. Sfortunatamente, quasi tutti i programmi copiano legittimamente i valori di memoria non inizializzati (poiché i compilatori eseguono il rilievo delle strutture per mantenere l'allineamento) e il controllo impaziente porta a centinaia di falsi positivi. Pertanto Memcheck non supporta il controllo impaziente in questo momento.

+1

Qual è la versione di Valgrind minima per utilizzare questa funzione? Sto usando 3.3.0 e non sembra gradire l'opzione. –

+6

@Robert: --track-origini è stato aggiunto in valgrind 3.4.0 – mark4o

16

Ciò significa che si sta tentando di stampare/emettere un valore che è almeno parzialmente non inizializzato. Puoi restringerlo in modo da sapere esattamente quale valore è? Successivamente, traccia il codice per vedere dove viene inizializzato. Le probabilità sono, vedrai che non è stato completamente inizializzato.

Se è necessario ulteriore aiuto, la pubblicazione delle sezioni pertinenti del codice sorgente potrebbe consentire a qualcuno di offrire ulteriori indicazioni.

EDIT

vedo che hai trovato il problema. Si noti che gli orologi valgrind per saltano condizionato o si muovono in base a variabili unitializzate. Ciò significa che emetterà un avvertimento solo se l'esecuzione del programma è alterata a causa del valore non inizializzato (ad esempio, il programma prende un ramo diverso in un'istruzione if, ad esempio). Dato che l'aritmetica attuale non ha comportato un salto o una mossa condizionale, valgrind non ti ha avvisato di ciò. Invece, ha propagato lo stato "non inizializzato" al risultato dell'istruzione che lo ha usato.

Può sembrare un controsenso che non avvertire immediatamente, ma come mark4o sottolineato, fa questo perché i valori non inizializzati vengono utilizzati in C tutto il tempo (esempi: imbottitura in strutture, il realloc() chiamata, ecc) quindi tali avvertimenti non sarebbero molto utili a causa della falsa frequenza positiva.

+0

Grazie. Ho appena scoperto cosa c'era di sbagliato, ma la cosa strana è che valgrind non ha riferito la cosa del valore unitializzato finché non è stato usato altrove .. – kamziro

+0

Questo è intenzionale. Se la copia o il passaggio di valori non inizializzati causasse una segnalazione di errore, si otterrebbe tutto il tempo dal riempimento delle strutture. – mark4o

Problemi correlati