localizzare “il salto condizionale o lo spostamento dipende dal / dai valore / i non inizializzato / i” messaggio valgrind

Quindi ho ricevuto alcuni misteriosi messaggi di valori non inizializzati da valgrind ed è stato piuttosto il mistero da dove il cattivo valore ha avuto origine.

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 > std::num_put<char, std::ostreambuf_iterator<char, std::char_traits > >::_M_insert_float(std::ostreambuf_iterator<char, std::char_traits >, 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 > >::do_put(std::ostreambuf_iterator<char, std::char_traits >, std::ios_base&, char, double) const (in /usr/lib/libstdc++.so.6.0.9) ==11366== by 0x42EE56F: std::ostream& std::ostream::_M_insert(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, diventa piuttosto criptico … soprattutto perché quando dice Class :: MethodX, a volte punta direttamente su 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?

Aggiornare:

Ho scoperto cosa non andava, ma la cosa strana è che valgrind non l’ha segnalato quando il valore negativo è stato utilizzato per la prima volta. È 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?

Usa l’opzione valgrind --track-origins=yes per far --track-origins=yes 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 viene riportato il valore non inizializzato, il manuale di valgrind afferma :

È importante capire che il tuo programma può copiare i dati indesiderati (non inizializzati) per quanto gli piace. 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.

Dalle FAQ di Valgrind :

Per quanto riguarda la necessità di segnalare le copie di valori di memoria non inizializzati, ciò è 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.

Ciò significa che stai provando a 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 hai bisogno di ulteriore aiuto, pubblicare le sezioni pertinenti del codice sorgente potrebbe consentire a qualcuno di offrire più indicazioni.

MODIFICARE

Vedo che hai trovato il problema. Nota che valgrind guarda per Salto condizionale o mossa basata su 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 controintuitivo che non ti avvisa immediatamente, ma come sottolineato da mark4o , lo fa perché i valori non inizializzati vengono utilizzati in C per tutto il tempo (esempi: padding nelle strutture, la chiamata realloc() , ecc.) Quindi questi avvertimenti non sarebbe molto utile a causa della falsa frequenza positiva.