Ispezione del contenuto del contenitore standard (std :: map) con gdb


93

Supponendo di avere qualcosa del genere:

#include <map>
int main(){
    std::map<int,int> m;
    m[1] = 2;
    m[2] = 4;
    return 0;
}

Vorrei poter ispezionare il contenuto della mappa che esegue il programma da gdb.
Se provo a utilizzare l'operatore pedice ottengo:

(gdb) p m[1]
Attempt to take address of value not located in memory.

L'uso del metodo trova non produce risultati migliori:

(gdb) p m.find(1)
Cannot evaluate function -- may be inlined

C'è un modo per farlo?

Risposte:


35

Penso che non ci sia, almeno non se la tua fonte è ottimizzata ecc. Tuttavia, ci sono alcune macro per gdb che possono ispezionare i contenitori STL per te:

http://sourceware.org/ml/gdb/2008-02/msg00064.html

Tuttavia, non lo uso, quindi YMMV


1
Grazie per il link; l'unica cosa è che le macro dipendono dalla versione delle librerie stl, cosa che preferirei evitare. +1
Paolo Tedesco

È anche un po 'frustrante che comandi come "plist foo std :: string" forniscano errori di sintassi. Sembra che value_type non possa contenere punteggiatura.
Bklyn

2
Non ho provato, ma se funziona come il resto di GDB, racchiudere il nome con il nome punteggiato tra virgolette singole dovrebbe farlo.
jpalecek

2
Nota: la funzionalità std :: map in questi script assume tipi di puntatore a 32 bit. Per le macchine a 64 bit, sostituire "+ 4" con "+ 8" ovunque nel file.
Kyle Simek

pvector non è definito nel mio gdb (versione 7.5.91.20130417-cvs-ubuntu).
Jeff

91

Le risposte esistenti a questa domanda sono molto obsolete. Con un recente GCC e GDB funziona solo TM grazie al supporto Python integrato in GDB 7.x e alle graziose stampanti libstdc ++ fornite con GCC.

Per l'esempio dell'OP ottengo:

(gdb) print m
$1 = std::map with 2 elements = {[1] = 2, [2] = 4}

Se non funziona automaticamente, vedi il primo punto elenco nella pagina di supporto STL del wiki GDB.

Puoi scrivere graziose stampanti Python anche per i tuoi tipi, vedi Pretty Printing nel manuale GDB.


2
Sì, ma altre domande vengono chiuse come duplicati di esso, quindi volevo che contenesse informazioni recenti.
Jonathan Wakely

1
Sto usando GDB 7.2 e quanto sopra funziona ... se hai una piccola collezione. Non ho ancora trovato alcun modo per stampare, ad esempio, l'elemento 1543 da un vettore 4K, a parte il ricorso all'utilizzo di strutture interne dell'implementazione STL.
padiglione

5
Sì, in GDB 7.2 e nel compilatore icpc ottengo l'errore Could not find operator[].
padiglione

11
Sfortunatamente non "funziona solo" in tutte le distribuzioni. Non è installato di default in Ubuntu 13.10 e ci sono problemi quando si tenta di installarlo manualmente
nietaki

1
@razeh, Fedora, RHEL (e i cloni RHEL). C'è una correzione in corso per far funzionare le stampanti anche su distribuzioni in cui GDB è collegato a Python 3
Jonathan Wakely

25

C'è sempre l'ovvio: definire la propria funzione di test ... Chiamala da gdb. Per esempio:

#define SHOW(X) cout << # X " = " << (X) << endl

void testPrint( map<int,int> & m, int i )
{
  SHOW( m[i] );
  SHOW( m.find(i)->first );
}

int
main()
{
    std::map<int,int> m;
    m[1] = 2;
    m[2] = 4;
    return 0;  // Line 15.
}

E:

....
Breakpoint 1 at 0x400e08: file foo.C, line 15.
(gdb) run
Starting program: /tmp/z/qD 

Breakpoint 1, main () at qD.C:15
(gdb) call testPrint( m, 2)
m[i] = 4
(*m.find(i)).first = 2
(gdb) 

16
fintanto che il processo è in esecuzione. non così utile per core-dump.
sean riley

2
Questo è un consiglio utile per eseguire il debug di GDB in generale, non solo con STL. Tengo un'intera libreria di funzioni di supporto gdb per molti dati difficili da recuperare, ad esempio write_cuda_array_as_image (). Nota che alcuni compilatori eliminano tutte le funzioni che non sono chiamate, quindi effettuo una chiamata a ciascuna funzione di supporto dopo "return 0;" del mio main. Anche dichiararli con extern "C" rende più facile chiamarli da gdb.
Kyle Simek

21

Quella stl-views.gdbera la migliore risposta che ci fosse, ma non più.

Questo non è ancora integrato nella linea principale GDB, ma ecco cosa ottieni usando il ramo 'archer-tromey-python' :

(gdb) list
1   #include <map>
2   int main(){
3       std::map<int,int> m;
4       m[1] = 2;
5       m[2] = 4;
6       return 0;
7   }
(gdb) break 6
Breakpoint 1 at 0x8048274: file map.cc, line 6.
(gdb) run

Breakpoint 1, main () at map.cc:6
6       return 0;
(gdb) print m
$1 = std::map with 2 elements = {
  [1] = 2,
  [2] = 4
}
(gdb) quit


1

Le risposte di cui sopra funzionano e vanno bene. Nel caso in cui si utilizzi stl-views.gdb, ecco il modo corretto di visualizzare le mappe e gli elementi al suo interno. Lascia che la tua mappa sia la seguente: std::map<char, int> myMap;

(gdb) pmap myMap char int

cioè pmap <variable_name> <left_element_type> <right_element_type>per vedere gli elementi nella mappa.

Spero che aiuti.


0

È possibile aggirare il secondo problema ( Cannot evaluate function -- may be inlined) assicurandosi che il compilatore utilizzi le informazioni di debug DWARF-2 (o 3 o 4) quando si compila il programma. DWARF-2 include informazioni in linea, quindi dovresti essere in grado di utilizzare uno dei metodi descritti per accedere agli elementi del tuo std::mapcontenitore.

Per compilare con le informazioni di debug DWARF-2, aggiungi il -gdwarf-2flag al comando di compilazione.


1
Ehm, sapere dove una funzione è stata inserita non consente a GDB di valutare le chiamate a quella funzione; GDB ha davvero bisogno di accedere a una copia fuori linea della funzione!
SamB
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.