2009-04-11 12 views
4

Ist es möglich, eine 'Dump' auf komplexe Strukturen oder sogar Arrays in C++, um visuell zu überprüfen, was sie in ihnen haben?Variable Dumping in C++

Ich denke an etwas ähnlich wie print_r() oder var_dump() in PHP.

Cheers, -Fin

Antwort

1

nicht generell möglich in C++, da es die Verwendung von Reflexion erfordert, die C++ nicht verfügt. Sie können natürlich Ihre eigene Funktion schreiben, um bestimmte Datenstrukturen zu speichern.

8

Die kurze Antwort lautet: Nein, es sei denn, Sie schreiben eine solche Routine selbst manuell.

Das ist oft keine schlechte Idee, aber es hat die üblichen Probleme mit der Klasse nicht mehr zu synchronisieren, wenn Sie häufig Mitglieder hinzufügen/ändern. Dies ist unvermeidbar, da C++ keinerlei Introspektion in struct s aufweist.

Wenn Sie sich für diesen Weg entscheiden, schreiben Sie am besten eine Überladung für std::ostream& operator<<(std::ostream& os, MyClass const&), die es Ihrer Klasse ermöglicht, in einen beliebigen IOStreams-Ausgabestream zu drucken.

+0

Das einzige Problem mit Operator liefert <<() ist, dass es eine Art Betreiber bedeutet >>() existiert, die in diesem Fall ist es nicht wahrscheinlich der Fall ist. Ich bevorzuge eine benannte DumpOn (ostream & os) -Funktion. –

+0

@Neil: Nun, ich stimme nicht zu, dass dies impliziert, aber ich sehe Ihren Standpunkt. Implementierender Operator >>() ist immer schwieriger, also stört mich das oft nicht, aber es ist immer schön, es auch zu haben. –

+0

Das andere Problem ist, dass es nicht ungewöhnlich ist, eine formatierte Ausgabemethode (op <<) UND eine Raw-Dump-Methode zu haben, in welchem ​​Fall der genannte Ansatz konsistenter sein kann. –

3

Zusätzlich zu den anderen Antworten können Sie, je nachdem, was Sie möchten und ob Sie sich für die Portabilität interessieren, möglicherweise die benötigten Informationen aus den Debuginformationen abrufen, die der Compiler generiert. Sie können die COFF/ELF/Anywhere-Formatdatei aus dem Build analysieren und erhalten damit die Informationen, die Sie benötigen, um die Namen und Typen der Variablen in Ihrem Objekt auszuarbeiten.

3

Wenn Sie eine Reflektion zu C++ hinzufügen (mit einer Drittanbieterbibliothek oder Herstellererweiterungen), können Sie eine Routine schreiben, um diese Reflektionsdaten zum Ablegen beliebiger Strukturen zu verwenden. Zum Beispiel habe ich einen Code, der die Reflex Bibliothek von CERN verwendet, um über die Member einer Klasse oder Struktur zu iterieren und sie an YAML auszugeben.

4

Normalerweise sind Debugger klug genug, dies zu tun.

In GDB können Sie:

print structure 

und in NTSD können Sie die uber-kühlen tun:

dt -r structure 

Wenn Sie diese nur verwenden Zwecke für das Debuggen, ich Lernen empfehlen die Debugger verwenden. Selbst wenn es etwas ist, das Sie als Sie protokollieren möchten (d. H. Eine zig Mal drucken), können Sie ein Haltepunktmakro setzen.

In NTSD:

bp yourdll!yourobject::yourfunction "dt -r structure;g" 

Und ich bin sicher, dass es eine Möglichkeit, es in GDB zu tun ist, als auch

0

der Tat, in einer Umgebung, wo Sie gdb zur Verfügung haben und Sie kompilieren Quellen mit Debugging-Symbolen aktiviert (zB -ggdb) können Sie Ihren Debugger haben (zB gdb von der Kommandozeile oder ddd, wenn Sie etwas grafisch wollen).

Betrachten Sie dieses Stück Code:

#include <string> 
#include <vector> 

struct test 
{ 
    int a; 
    float b; 
    std::string c; 
}; 

int main() 
{ 
    std::vector<int> v; 

    test t; 
    t.a=1; 
    t.b=2.0; 
    t.c="hello there"; 


    return 0; 
} 

Wenn gdb fragen höflich kann es mir die folgende Ausgabe geben:

 
(gdb) break 20 
Breakpoint 1 at 0x8048622: file bla.cpp, line 20. 
(gdb) run 
Starting program: /home/edb/a.out 

Breakpoint 1, main() at bla.cpp:21 
21  return 0; 
(gdb) print t 
$1 = {a = 1, b = 2, c = {static npos = 4294967295, 
    _M_dataplus = {> = {> = {}, }, _M_p = 0x96b6014 "hello there"}}} 
(gdb) ping v 
Undefined command: "ping". Try "help". 
(gdb) print v 
$2 = { >> = { 
    _M_impl = {> = {> = {}, }, _M_start = 0x0, _M_finish = 0x0, 
     _M_end_of_storage = 0x0}}, } 

Edit: beachten Sie, dass diese Daten von einem Debugger Kontext zur Verfügung steht, für Um diese Dumps zur Laufzeit zu generieren, müssen Sie eine eigene Dump-/Formatierungsfunktion vorsehen, die typischerweise durch Überladen des < <-Operators in C++ erfolgt.

0

Warum verwenden Sie keine Binärdateien? fstream hat einen binären Modus, und Sie können jeden Typ außer struct,class,namespace oder STL-Listen (wie Vektor, Warteschlange) ablegen. Möchten Sie Struktur, Klasse, Namespace (oder STL-Liste) zu binären dump? Machen Sie eine Funktion und legen Sie jede Variable in der Datei ab! Das Ende! Das wäre nicht so schwer ... aber mehr Hilfe? Sehen Sie sich dieses Code-Snippet an!

#include <iostream> 
#include <fstream>//ofstream,ifstream 
using namespace std; 
ifstream myBdumpin ("data.bin"/*filename*/, ios::in);//ifstream = input 
ofstream myBdumpout ("data.bin"/*filename*/, ios::out);//ofstream = output 
int main() 
{ 
    char a[8]="Binary!" 
    myBdumpout << a; 
    char b[8]; 
    myBdumpin >> b; 
    if(a == b)cout << "It worked!" << endl; 
    else cout << "It failed..." << endl; 
    return 0; 
} 

Es sollte funktionieren ...