Wie ändert die Debugging-Option -g die binäre ausführbare Datei?

74

Beim Schreiben von C / C ++ - Code muss zum Debuggen der ausführbaren Binärdatei die Debug-Option auf dem Compiler / Linker aktiviert sein. Im Fall von GCC ist die Option -g. Wie wirkt sich das auf die ausführbare Binärdatei aus, wenn die Debug-Option aktiviert ist? Welche zusätzlichen Daten werden in der Datei gespeichert, die es dem Debugger ermöglichen, so zu funktionieren?

Jon Ball
quelle

Antworten:

71

-g weist den Compiler an, Symboltabelleninformationen in der ausführbaren Datei zu speichern. Dazu gehören unter anderem:

  • Symbolnamen
  • Geben Sie info für Symbole ein
  • Dateien und Zeilennummern, aus denen die Symbole stammen

Debugger verwenden diese Informationen, um aussagekräftige Namen für Symbole auszugeben und Anweisungen bestimmten Zeilen in der Quelle zuzuordnen.

Bei einigen Compilern werden durch die Angabe von -g bestimmte Optimierungen deaktiviert. Beispielsweise setzt icc die Standardoptimierungsstufe mit -g auf -O0, sofern Sie nicht ausdrücklich -O [123] angeben. Auch wenn Sie -O [123] angeben, werden Optimierungen, die die Stapelverfolgung verhindern, weiterhin deaktiviert (z. B. Entfernen von Frame-Zeigern von Stack-Frames. Dies hat nur einen geringen Einfluss auf die Leistung).

Bei einigen Compilern deaktiviert -g Optimierungen, die verwirren können, woher Symbole stammen (Neuanordnung von Anweisungen, Abrollen von Schleifen, Inlining usw.). Wenn Sie mit der Optimierung debuggen möchten, können Sie -g3 mit gcc verwenden, um einige davon zu umgehen. Zusätzliche Debug-Informationen zu Makros, Erweiterungen und Funktionen, die möglicherweise eingebunden wurden, werden hinzugefügt. Dies kann es Debuggern und Leistungstools ermöglichen, optimierten Code der ursprünglichen Quelle zuzuordnen, aber es ist die beste Anstrengung. Einige Optimierungen entstellen den Code wirklich.

Weitere Informationen finden Sie in DWARF , dem Debugging-Format, das ursprünglich für ELF (das Binärformat für Linux und andere Betriebssysteme) entwickelt wurde.

tgamblin
quelle
1
Nur um dies hinzuzufügen, kann es auch die ausführbare Datei verlangsamen. Ich habe OpenMP-Code mit dem Sun Studio-Compiler getestet, und beim Debuggen von Informationen lief der Code viel langsamer. Nur etwas zu beachten.
Mike
6
Sofern das Flag -g im Sun-Compiler einige Optimierungen nicht deaktiviert, sollten Debug-Informationen Ihren Code NICHT verlangsamen.
Todd Gamblin
Dies ist OpenMP-Code, der ihn verlangsamt hat. Ich habe mit Fraktalen gespielt und an der Verwendung der OpenMP-Compiler-Erweiterungen gearbeitet. Der Code in einem einzelnen Thread lief langsamer als der Nicht-OpenMP-Code in einem einzelnen Thread. Ich habe das Debuggen deaktiviert und die Geschwindigkeit ausgeglichen.
Mike
Notiert. Das ist eigentlich irgendwie interessant. Vielleicht werden zusätzliche Dinge eingefügt , um dem Debugger Informationen über parallele Regionen zu geben ... Hier ( docs.sun.com/source/819-3683/OpenMP.html ) heißt es, dass Sie den Master-Thread wieder der Quelle zuordnen können, aber nicht Sklaven, was auch seltsam erscheint.
Todd Gamblin
Ich denke, das ist der Fall, hat natürlich keinen Einfluss auf GCC, hat mich sicherlich überrascht, als der Single-Thread-Code von 11 Sekunden auf 22 Sekunden stieg: / Bei deaktiviertem Debugging und 4 Threads (ich habe einen Q6600) fiel er auf etwa 3 Sekunden .
Mike
10

Der ausführbaren Datei wird eine Symboltabelle hinzugefügt, die Funktions- / Variablennamen Datenpositionen zuordnet, sodass Debugger aussagekräftige Informationen und nicht nur Zeiger zurückmelden können. Dies wirkt sich nicht auf die Geschwindigkeit Ihres Programms aus, und Sie können die Symboltabelle mit dem Befehl 'strip' entfernen.

Alexandra Franks
quelle
8

Zusätzlich zu den Debugging- und Symbolinformationen
Google DWARF (Ein Entwicklerwitz auf ELF)

Standardmäßig sind die meisten Compiler-Optimierungen deaktiviert, wenn das Debuggen aktiviert ist.
Der Code ist also eher die reine Übersetzung der Quelle in Maschinencode als das Ergebnis vieler hochspezialisierter Transformationen, die zum Freigeben von Binärdateien angewendet werden.

Der wichtigste Unterschied (meiner Meinung nach) zum
Speicher in Debug-Builds wird jedoch normalerweise auf einige compilerspezifische Werte initialisiert, um das Debuggen zu erleichtern. In Release-Builds wird der Speicher nur initialisiert, wenn der Anwendungscode dies ausdrücklich tut.

Weitere Informationen finden Sie in der Compiler-Dokumentation:
Ein Beispiel für DevStudio ist jedoch:

  • 0xCDCDCDCD Wird im Heap zugewiesen, aber nicht initialisiert
  • 0xDDDDDDDD Freigegebener Heapspeicher.
  • 0xFDFDFDFD "NoMansLand" -Zäune werden automatisch an der Grenze des Heapspeichers platziert. Sollte niemals überschrieben werden. Wenn Sie eines überschreiben, verlassen Sie wahrscheinlich das Ende eines Arrays.
  • 0xCCCCCCCC Wird auf dem Stapel zugewiesen, aber nicht initialisiert
Martin York
quelle
7

-g fügt der ausführbaren Datei Debugging-Informationen hinzu, z. B. die Namen von Variablen, die Namen von Funktionen und Zeilennummern. Auf diese Weise kann ein Debugger wie z. B. gdb Code zeilenweise durchlaufen, Haltepunkte festlegen und die Werte von Variablen überprüfen. Aufgrund dieser zusätzlichen Informationen erhöht die Verwendung von -g die Größe der ausführbaren Datei.

Außerdem ermöglicht gcc die Verwendung von -g zusammen mit -O-Flags, die die Optimierung aktivieren. Das Debuggen einer optimierten ausführbaren Datei kann sehr schwierig sein, da Variablen möglicherweise nicht mehr optimiert werden oder Anweisungen in einer anderen Reihenfolge ausgeführt werden. Im Allgemeinen ist es eine gute Idee, die Optimierung bei Verwendung von -g zu deaktivieren, obwohl dies zu einem viel langsameren Code führt.

Dima
quelle
3

Es gibt einige Überschneidungen mit dieser Frage, die das Problem von der anderen Seite abdeckt.

Rob Walker
quelle
3

Nur aus Interesse können Sie einen Hexeditor aufbrechen und sich eine ausführbare Datei ansehen, die mit -gund ohne erstellt wurde. Sie können die Symbole und Dinge sehen, die hinzugefügt werden. Es kann auch die Assembly ( -S) ändern , aber ich bin nicht sicher.

Bernard
quelle
3

Einige Betriebssysteme (wie z / OS ) erzeugen eine "Seitendatei", die die Debug-Symbole enthält. Dies hilft zu vermeiden, dass die ausführbare Datei mit zusätzlichen Informationen aufgebläht wird.

Anthony Giorgio
quelle