Episodio 13: di Christian Biesinger in Madison, WI (marzo 2020)
Puntate precedenti
Ti ritrovi a eseguire lo stesso test più volte nel debugger,
cercando di capire come il codice non funzionasse? Abbiamo uno strumento per te.
Facile da installare e configurare, registrerà una traccia di esecuzione e conferisce
magici nuovi poteri a gdb
. Fai un passo indietro, esegui a ritroso, vedi dove le variabili hanno modificato il loro valore o l'ultima volta che una funzione è stata chiamata su un oggetto (utilizzando i punti di interruzione condizionali).
Su Linux, puoi utilizzare rr. Installa utilizzando sudo apt-get install rr
o
da https://rr-project.org/.
Questa funzionalità non è ufficialmente supportata, ma è molto utile. rr
funziona
per registrare una traccia, quindi ririprodurla.
rr record .../content_shell --no-sandbox --disable-hang-monitor --single-process
# record the trace. --single-process is optional, see below. The other flags are required.
rr replay # This will replay the last trace
(gdb) # rr uses GDB to let you replay traces
In pratica, gli indirizzi di sincronizzazione e puntatore rimangono invariati ogni volta che ripeti la stessa traccia. Le tracce possono essere rese portabili utilizzando rr pack
in modo da
copiarle su un'altra macchina e riprodurle da lì oppure riprodurle anche dopo
la ricompilazione. Esegui il programma utilizzando continue
. Puoi utilizzare tutti i normali comandi GDB -b
, next
, watch
e così via. Tuttavia, puoi anche utilizzare reverse-next (rn
), reverse-cont (rc
), reverse-step (rs
), reverse-fin.
Questi punti di interruzione rispettano comunque gli eventuali punti di interruzione impostati. Ad esempio:
(gdb) c # Execute to the end
(gdb) break blink::LayoutFlexibleBox::UpdateLayout
(gdb) rc # Run back to the last layout call
Thread 5 hit Breakpoint 1, blink::LayoutBlock::UpdateLayout (
this=0x121672224010)
(gdb) # Inspect anything you want here. To find the previous Layout call on this object:
(gdb) cond 1 this == 0x121672224010
(gdb) rc
Thread 5 hit Breakpoint 1, blink::LayoutBlock::UpdateLayout (
this=0x121672224010)
(gdb) watch -l style_.ptr_ # Or find the last time the style_ was changed
(gdb) rc
Thread 5 hit Hardware watchpoint 2: -location style_.ptr_
Old value = (const blink::ComputedStyle *) 0x1631ad3dbb0
New value = (const blink::ComputedStyle *) 0x0
0x00007f68cabcf78e in std::__Cr::swap<blink::ComputedStyle const*> (
In questo esempio, ho utilizzato --single-process
per semplicità, ma non è
necessario. RR può tracciare più processi; dopo la registrazione, puoi visualizzare un elenco utilizzando rr ps
e selezionarne uno da riprodurre con rr replay -f PID
.
RR può essere utile in molti modi. Puoi utilizzare altri comandi, ad esempio quando scoprire a quale numero di evento ti trovi oppure rr replay -M
per annotare stdout
con un ID processo e un numero di evento per ogni riga. Per ulteriori dettagli, consulta il sito web e la documentazione di RR.