Perché GDB salta in modo imprevedibile tra le righe e stampa le variabili come "<valore ottimizzato>"?


84

Qualcuno può spiegare questo comportamento di gdb?

Perché dopo aver eseguito la riga 903, viene eseguita nuovamente la stessa per 905 908 910?

Un'altra cosa è che foundè una boolvariabile di tipo, quindi perché viene visualizzata value optimized out? Non sono in grado di impostare anche il valore di found.

Questa sembra essere un'ottimizzazione del compilatore (in questo caso la sua -O2); come posso ancora impostare il valore di found?


8
durante il debug, è generalmente una buona idea compilare con -O0 poiché l'ottimizzazione porta a quel tipo di problemi.
LiraNuna

Risposte:


115

Per eseguire il debug del codice ottimizzato, impara il linguaggio assembly / macchina.

Usa la modalità TUI GDB. La mia copia di GDB lo abilita quando digito il meno e Invio. Quindi digita Cx 2 (ovvero tieni premuto Control e premi X, rilascia entrambi e quindi premi 2). Ciò lo metterà nella sorgente divisa e nel display di smontaggio. Quindi utilizzare stepie nextiper spostare un'istruzione macchina alla volta. Usa Cx o per passare tra le finestre TUI.

Scarica un PDF sul linguaggio macchina della tua CPU e sulle convenzioni di chiamata delle funzioni. Imparerai rapidamente a riconoscere cosa viene fatto con gli argomenti della funzione e i valori di ritorno.

È possibile visualizzare il valore di un registro utilizzando un comando GDB come p $eax


Ho ancora il problema "ottimizzato" e il valore della variabile non è mostrato nelle altre finestre, ma, comunque, è un'ottima informazione, grazie!
Tom Brito

16
@TomBrito: Ottimizzato significa che la variabile non è in memoria. Probabilmente è solo in un registro della CPU, il che significa che è necessario leggere il disassemblaggio e stampare i valori del registro per trovarlo.
Zan Lynx

@Zan Lynx: non sono sicuro di essere d'accordo con la tua analisi. I simboli DWARF hanno informazioni sufficienti per estrarre i valori dai registri. Forse ciò che significa qui è che il compilatore ha determinato che la variabile può essere scartata in modo sicuro nel momento in cui l'esecuzione raggiunge la riga corrente. In quel caso lo spazio di archiviazione in cui risiede la variabile è stato probabilmente riutilizzato per qualcos'altro. Penso che tu abbia ragione sul fatto che questo normalmente accadrebbe solo se la variabile fosse registrata, però.
Ian Ni-Lewis

@ IanNi-Lewis: non so quale versione di DWARF stai usando, ma nella mia esperienza GDB non può stampare una variabile che è stata memorizzata in un registro.
Zan Lynx

Sono sicuro che hai ragione. La mia esperienza con DWARF deriva dalla scrittura del mio parser, non dall'utilizzo di gdb, quindi non so davvero di cosa sia capace gdb.
Ian Ni-Lewis

75

Ricompila senza ottimizzazioni (-O0 su gcc).


17
Anche -O0 può produrre codice ottimizzato (cercando di lottare con questo in questo momento), anche se non sono sicuro del perché.
Chris Gregg

@ChrisGregg ho avuto lo stesso problema! Hai scoperto qual è il problema?
Paolo M

1
@paolom sembra che potrebbe essere un problema di clang, quindi ho compilato con g ++ invece per scopi di debug, sfortunatamente.
Chris Gregg

Spesso questa non è una soluzione, specialmente se hai un core dump dalla produzione e / o non sei in grado di riprodurre il problema nell'ambiente di sviluppo.
smbear

39

Dichiara trovato come "volatile". Questo dovrebbe dire al compilatore di NON ottimizzarlo.


1
Anche quando dichiaro alcune variabili "volatili" nel debugger gdb, lo mostra come variabile out ottimizzata! C'è altro in questo?
M. Rez

11

Il compilatore inizierà a fare cose molto intelligenti con le ottimizzazioni attivate. Il debugger mostrerà il codice che salta avanti e indietro molto a causa del modo ottimizzato di memorizzare le variabili nei registri. Questo è probabilmente il motivo per cui non è possibile impostare la variabile (o in alcuni casi vederne il valore) poiché è stata distribuita in modo intelligente tra i registri per la velocità, piuttosto che avere una posizione di memoria diretta a cui il debugger può accedere.

Compilare senza ottimizzazioni?


6

In genere, i valori booleani utilizzati nei rami immediatamente dopo essere stati calcolati in questo modo non vengono mai effettivamente memorizzati nelle variabili. Invece, il compilatore si dirama direttamente dai codici di condizione impostati dal confronto precedente. Per esempio,

Di solito si compila in qualcosa di simile:

Notare come il "bool" non viene mai effettivamente memorizzato da nessuna parte.


4

Non puoi praticamente impostare il valore di trovato. Il debug di programmi ottimizzati raramente vale la pena, il compilatore può riorganizzare il codice in modi che non corrisponderà in alcun modo al codice sorgente (a parte produrre lo stesso risultato), confondendo così i debugger a non finire.


4

Quando si esegue il debug di programmi ottimizzati (che potrebbe essere necessario se il bug non viene visualizzato nelle build di debug), spesso è necessario comprendere il compilatore di assembly generato.

Nel tuo caso particolare, il valore di ritorno di cpnd_find_exact_ckptinfoverrà memorizzato nel registro che viene utilizzato sulla tua piattaforma per i valori di ritorno. Su ix86, sarebbe %eax. Su x86_64:, %raxecc. Potrebbe essere necessario cercare su Google la "convenzione di chiamata della procedura [del processore]" se non è presente nessuna delle precedenti.

Puoi esaminare quel registro in GDBe puoi impostarlo. Ad esempio su ix86:


0

Sto usando QtCreator con gdb.

Aggiunta

Funziona bene per me

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.