Wie drucke ich die Elemente eines C ++ - Vektors in GDB?

Antworten:

79

Um den Inhalt von vector std :: vector myVector anzuzeigen, geben Sie einfach GDB ein:

(gdb) print myVector

Dies erzeugt eine Ausgabe ähnlich der folgenden:

$1 = std::vector of length 3, capacity 4 = {10, 20, 30}

Um dies zu erreichen, benötigen Sie GDB 7 (ich habe es auf GDB 7.01 getestet) und einen Python-Pretty-Drucker. Der Installationsprozess dieser wird im GDB-Wiki beschrieben .

Darüber hinaus funktioniert dies nach der obigen Installation gut mit der Eclipse C ++ - Debugger-GUI (und jeder anderen IDE, die GDB verwendet, wie ich denke).

Michał Oniszczuk
quelle
16
Dies funktioniert gut, solange die Vektorelemente direkt interpretierbar sind. Es hilft jedoch nicht, wenn der Vektor Zeiger auf die interessierenden Elemente enthält.
Wallyk
Ich finde die GDB-Wiki- Seite ehrlich gesagt nicht besonders lesbar, vielleicht weil sie jetzt "leicht" veraltet ist? Zum Beispiel hatte ich den Eindruck, dass der vorgeschlagene Inhalt des $HOME/.gdbinitnotwendig war. Im Moment habe ich überhaupt keine solche Datei und gdbzeige den Inhalt von korrekt an std::vector. Da ich jedoch während meiner "Rambling" -Versuche gerade installiert und dann nicht kristallisiert habe cgdbund bereits libstdc++5installiert hatte, habe ich keine Ahnung, warum das hübsche Drucken nicht funktioniert hat, während es jetzt funktioniert.
Enrico Maria De Angelis
257

Gehen Sie mit GCC 4.1.2 wie folgt vor, um den gesamten std :: vector <int> mit dem Namen myVector zu drucken:

print *(myVector._M_impl._M_start)@myVector.size()

Um nur die ersten N Elemente zu drucken, gehen Sie wie folgt vor:

print *(myVector._M_impl._M_start)@N

Erläuterung

Dies hängt wahrscheinlich stark von Ihrer Compilerversion ab, aber für GCC 4.1.2 lautet der Zeiger auf das interne Array:

myVector._M_impl._M_start 

Der GDB-Befehl zum Drucken von N Elementen eines Arrays ab Zeiger P lautet:

print P@N

Oder in Kurzform (für eine Standard-.gdbinit):

p P@N
John Carter
quelle
4
Hehe, es ist etwas, das mich schon früher nervt, also habe ich es heute Morgen nachgeschlagen und es mir als Memo hinzugefügt (wie Jeff selbst empfohlen hat).
John Carter
3
Auch wenn Sie nur ein bestimmtes Vektorelement möchten, myVector._M_impl._M_start + n (für das n-te Element)
Seefahrer
1
Ich arbeite nicht für mich. Cannot evaluate function -- may be inlined
Wallyk
1
So drucken Sie ein einzelnes Element, z. B. das 2. Element: print (myVector._M_impl._M_start) [2]
jfritz42
2
Um die speziellen Namen ( _M_implusw.) für Ihren Compiler unter GDB 7.0+ zu finden, verwenden Sieprint /r myVector
Eponymous
14

Das "Beobachten" von STL-Containern beim Debuggen ist ein Problem. Hier sind 3 verschiedene Lösungen, die ich in der Vergangenheit verwendet habe. Keine davon ist perfekt.

1) Verwenden Sie GDB-Skripte von http://clith.com/gdb_stl_utils/ Mit diesen Skripten können Sie den Inhalt fast aller STL-Container drucken. Das Problem ist, dass dies für verschachtelte Container wie einen Stapel von Sets nicht funktioniert.

2) Visual Studio 2005 bietet eine fantastische Unterstützung für das Ansehen von STL-Containern. Dies funktioniert für verschachtelte Container, dies gilt jedoch nur für deren Implementierung für STL und funktioniert nicht, wenn Sie einen STL-Container in einen Boost-Container einfügen.

3) Schreiben Sie Ihre eigene Druckfunktion (oder -methode) für das bestimmte Element, das Sie beim Debuggen drucken möchten, und verwenden Sie "Aufruf" in GDB, um das Element zu drucken. Beachten Sie, dass wenn Ihre Druckfunktion an keiner Stelle im Code aufgerufen wird, g ++ die Eliminierung von totem Code durchführt und die Funktion 'Drucken' von GDB nicht gefunden wird (Sie erhalten eine Meldung, dass die Funktion inline ist). Kompilieren Sie also mit -fkeep-inline-Funktionen

Nikhil
quelle
11

Geben Sie Folgendes in ~ / .gdbinit ein

define print_vector
    if $argc == 2
        set $elem = $arg0.size()
        if $arg1 >= $arg0.size()
            printf "Error, %s.size() = %d, printing last element:\n", "$arg0", $arg0.size()
            set $elem = $arg1 -1
        end
        print *($arg0._M_impl._M_start + $elem)@1
    else
        print *($arg0._M_impl._M_start)@$arg0.size()
    end
end

document print_vector
Display vector contents
Usage: print_vector VECTOR_NAME INDEX
VECTOR_NAME is the name of the vector
INDEX is an optional argument specifying the element to display
end

Zeigen Sie nach dem Neustart von gdb (oder der Beschaffung von ~ / .gdbinit) die zugehörige Hilfe wie folgt an

gdb) help print_vector
Display vector contents
Usage: print_vector VECTOR_NAME INDEX
VECTOR_NAME is the name of the vector
INDEX is an optional argument specifying the element to display

Anwendungsbeispiel:

(gdb) print_vector videoconfig_.entries 0
$32 = {{subChannelId = 177 '\261', sourceId = 0 '\000', hasH264PayloadInfo = false, bitrate = 0,     payloadType = 68 'D', maxFs = 0, maxMbps = 0, maxFps = 134, encoder = 0 '\000', temporalLayers = 0 '\000'}}
badeip
quelle
2
Danke für den Code! Ich denke, es gibt einen Tippfehler und "print * ($ arg0._M_impl._M_start + $ elem) @ 1" sollte "print * ($ arg0._M_impl._M_start + $ arg1) @ 1" sein? Ich verwende die folgende Modifikation: definiere print_vector wenn $ argc == 2 wenn $ arg1> = $ arg0.size () - 1 printf "Fehler,% s.size () =% d, Drucken des letzten Elements: \ n", " $ arg0 ", $ arg0.size () - 1 Enddruck * ($ arg0._M_impl._M_start + $ arg1) @ 1 sonst print * ($ arg0._M_impl._M_start) @ $ arg0.size () Ende Ende
user1541776
el Magnifico! Mokkas Gracias
Truthadjustr
0

Ein bisschen zu spät zur Party, also meistens eine Erinnerung an mich, wenn ich das nächste Mal diese Suche mache!

Ich konnte verwenden:

p/x *(&vec[2])@4

um 4 Elemente (als Hex) von vecAnfang an zu drucken vec[2].

Mike P.
quelle