Überprüfen des Inhalts von Standardcontainern (std :: map) mit gdb

92

Angenommen, wir haben so etwas:

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

Ich möchte in der Lage sein, den Inhalt der Karte zu überprüfen, auf der das Programm von gdb ausgeführt wird.
Wenn ich versuche, den Indexoperator zu verwenden, erhalte ich:

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

Die Verwendung der Suchmethode führt nicht zu besseren Ergebnissen:

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

Gibt es eine Möglichkeit, dies zu erreichen?

Paolo Tedesco
quelle

Antworten:

35

Ich denke, es gibt keine, zumindest nicht, wenn Ihre Quelle optimiert ist usw. Es gibt jedoch einige Makros für GDB, die STL-Container für Sie überprüfen können:

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

Ich benutze dies jedoch nicht, also YMMV

jpalecek
quelle
1
Danke für den Link; Das einzige ist, dass Makros von der Version der STL-Bibliotheken abhängig sind, die ich lieber vermeiden möchte. +1
Paolo Tedesco
Es ist auch ein bisschen frustrierend, dass Befehle wie "plist foo std :: string" Syntaxfehler verursachen. Es scheint, dass der value_type keine Interpunktion enthalten kann.
Bklyn
2
Ich habe es nicht versucht, aber wenn dies genauso funktioniert wie der Rest von GDB, sollte es ausreichen, den Namen in einfache Anführungszeichen zu setzen.
Jpalecek
2
Hinweis: Die std :: map-Funktionalität in diesen Skripten setzt 32-Bit-Zeigertypen voraus. Ersetzen Sie bei 64-Bit-Computern überall in der Datei "+ 4" durch "+ 8".
Kyle Simek
pvector ist in meiner GDB nicht definiert (Version 7.5.91.20130417-cvs-ubuntu).
Jeff
90

Die vorhandenen Antworten auf diese Frage sind sehr veraltet. Mit einer aktuellen GCC und GDB es funktioniert einfach TM dank der integrierten Python Unterstützung in GDB 7.x und der libstdc ++ ziemlich Drucker , die mit GCC kommen.

Für das Beispiel des OP bekomme ich:

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

Wenn es für Sie nicht automatisch funktioniert, sehen Sie den ersten Aufzählungspunkt auf der STL-Support- Seite des GDB-Wikis.

Sie können auch hübsche Python-Drucker für Ihre eigenen Typen schreiben, siehe Hübsches Drucken im GDB-Handbuch.

Jonathan Wakely
quelle
2
Ja, aber andere Fragen werden als Duplikate davon geschlossen, daher wollte ich, dass sie aktuelle Informationen enthalten.
Jonathan Wakely
1
Ich benutze GDB 7.2 und das oben genannte funktioniert ... wenn Sie eine kleine Sammlung haben. Ich habe immer noch keine Möglichkeit gefunden, das Element 1543 aus einem 4K-Vektor zu drucken, außer auf interne Strukturen der STL-Implementierung zurückzugreifen.
Pavon
5
Ja, in GDB 7.2 und dem icpc-Compiler erhalte ich den Fehler Could not find operator[].
Pavon
11
Leider funktioniert es nicht in allen Distributionen. Es ist nicht standardmäßig in Ubuntu 13.10 installiert und es gibt Probleme, wenn Sie versuchen, es manuell zu installieren
Nietaki
1
@razeh, Fedora, RHEL (und RHEL-Klone). Es gibt eine Korrektur, die bewirkt, dass die Drucker auch in Distributionen funktionieren, in denen GDB mit Python 3 verknüpft ist
Jonathan Wakely
25

Es gibt immer das Offensichtliche: Definieren Sie Ihre eigene Testfunktion ... Rufen Sie sie von gdb aus auf. Z.B:

#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.
}

Und:

....
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) 
Mr.Ree
quelle
16
solange der Prozess läuft. nicht so nützlich für Core-Dumps.
Sean Riley
2
Dies ist ein nützlicher Ratschlag zum Debuggen von GDB im Allgemeinen, nicht nur mit STL. Ich behalte eine ganze Bibliothek von GDB-Hilfsfunktionen für viele schwer abrufbare Daten, z. B. write_cuda_array_as_image (). Beachten Sie, dass einige Compiler alle Funktionen entfernen, die nicht aufgerufen werden. Daher rufe ich jede Hilfsfunktion nach "return 0;" meines Mains auf. Das Deklarieren mit externem "C" erleichtert das Aufrufen von gdb.
Kyle Simek
21

Das war stl-views.gdbfrüher die beste Antwort, aber nicht mehr.

Dies ist noch nicht in die GDBHauptzeile integriert , aber hier ist, was Sie mit dem Zweig 'archer-tromey-python' erhalten :

(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
Angestellt Russisch
quelle
12

Versuchen Sie, STL-Container zu de-referenzieren: auf dieser Seite: http://www.yolinux.com/TUTORIALS/GDB-Commands.html

anand
quelle
Diese scheinen das Geschäft zu sein!
Richard Corden
Es sind tatsächlich die gleichen Makros wie in der vorherigen Antwort :) Ich fürchte, es gibt keine einfachere Lösung.
Paolo Tedesco
Was ist der Befehl? Sie haben es geschafft, uns mit zahlreichen irrelevanten Informationen außerhalb des Unternehmens zu betreiben. Ich interessiere mich nicht für "Wie starte ich GDB?" Und die anderen.
JWW
1

Die obigen Antworten funktionieren und sind in Ordnung. Wenn Sie stl-views.gdb verwenden, finden Sie hier die richtige Methode zum Anzeigen der darin enthaltenen Karten und Elemente. Lassen Sie Ihre Karte wie folgt aussehen: std::map<char, int> myMap;

(gdb) pmap myMap char int

dh pmap <variable_name> <left_element_type> <right_element_type>um die Elemente in der Karte zu sehen.

Hoffentlich hilft das.

Mazhar MIK
quelle
0

Sie können das zweite Problem ( Cannot evaluate function -- may be inlined) umgehen, indem Sie sicherstellen, dass Ihr Compiler beim Kompilieren Ihres Programms DWARF-2-Debugging-Informationen (oder 3 oder 4) verwendet. DWARF-2 enthält Inlining-Informationen, sodass Sie eine der beschriebenen Methoden verwenden können sollten, um auf Elemente Ihres std::mapContainers zuzugreifen .

Fügen Sie zum Kompilieren mit DWARF-2-Debuginformationen das -gdwarf-2Flag zu Ihrem Kompilierungsbefehl hinzu.

Dan
quelle
1
Wenn Sie wissen, wo eine Funktion eingefügt wurde, kann GDB Aufrufe dieser Funktion nicht auswerten. GDB braucht wirklich Zugriff auf eine Offline-Kopie der Funktion!
SamB