Debuggen von C++Builder-Anwendungen für 64-Bit-Windows

Aus RAD Studio
Wechseln zu: Navigation, Suche

Nach oben zu C++Builder-Anwendungsentwicklung für 64-Bit-Windows


LLDB-basierter C++-Debugger für WIN64

In RAD Studio 10.4 wurde ein neuer, auf LLDB basierter Debugger für C++ für Win64 eingeführt. Der Compiler verwendet das Format von DWARF Version 4 für Debug-Informationen.

Der neue LLDB-basierte Debugger von RAD Studio bietet eine verbesserte Stabilität beim Debuggen und ermöglicht durch eine neue Debugger-Technologie und die generierten Debug-Informationen eine verbesserte Auswertung, Untersuchung und andere Debugger-Funktionen. Außerdem unterstützt der Debugger die Auswertung komplexer Typen, wie STL-Sammlungen oder Strings, über Formatierer.

Formatierer

Ein häufiges Problem beim Debuggen von C++-Anwendungen ist die Untersuchung oder Auswertung komplexer Typen. Für die Auswertung des Inhalts einer std::map (zum Beispiel) ist die Kenntnis des Layouts des Typs erforderlich, und der Array-Zugriffsoperator [] ist möglicherweise für den Debugger nicht verfügbar, wenn er im Code nie aufgerufen wurde oder immer Inline angegeben wurde und daher nicht aufrufbar ist. Ähnliche Probleme gibt es bei anderen Typen, einschließlich Strings, und möglicherweise sogar bei Ihren eigenen Typen.

Dies wird durch die Verwendung von Formatierern gelöst. Ein Formatierer ist ein kleines Python-Skript, das beim Debuggen eines bestimmten Typs hilft. RAD Studio wird mit Formatierern für gängige Typen ausgeliefert, und Sie können bei Bedarf eigene Formatierer für Ihre Typen hinzufügen.

Die folgenden Formatierer sind für gängige STL- und Delphi-Typen verfügbar.

* std::string and std::wstring 
* String (UnicodeString), AnsiString, UTF8String, WideString. 
* std::vector 
* std::deque 
* std::stack 
* std::map 
* std::shared_ptr

Benutzerdefinierte Formatierer

Um einen eigenen Formatierer hinzuzufügen, erstellen Sie eine neue Python-Datei und fügen der Datei bin\Windows\lldb\.lldbinit eine Zeile mit einem Verweis auf Ihr neues Python-Skript hinzu. Weitere Informationen zum Schreiben eigener Formatierer finden Sie hier:

C++Builder für 64-Bit-Windows

Der C++Builder-Compiler für 64-Bit-Windows (BCC64) erzeugt Debug-Informationen im DWARF-Format, das sich von dem Format, das von BCC32 und BCCOSX verwendet wird, unterscheidet. Im Allgemeinen entspricht das Debuggen von C++-Anwendungen für 64-Bit-Windows jedoch dem Debuggen von C++-Anwendungen für 32-Bit-Windows. Es gibt einige Unterschiede, die im Folgenden beschrieben werden:

  • Einige Debugger-Funktionen werden nicht unterstützt. Das Debuggen von Eigenschaften, Closures, Klassenmethoden und anderen Erweiterungen der Delphi-Sprache wird derzeit nicht unterstützt.
    Beispielsweise werden im Debug-Inspektor die Registerkarten Methoden und Eigenschaften für C++-Anwendungen für 64-Bit-Windows nicht angezeigt.
  • Unicode, Codeseiten und Lokalisierung werden nicht vollständig unterstützt.
    Beispielsweise wird Unicode nicht in Bezeichnernamen unterstützt, und Codeseiten werden nicht vom C++-Debugger für 64-Bit-Windows unterstützt.
  • Bei der Auswertung eines 64-Bit-Windows-Registers muss dem Registernamen ein $ (z.B. $rax) vorangestellt werden.
    Siehe Auswerten/Ändern.
  • Funktionsaufrufe, die Exceptions auslösen, werden folgendermaßen behandelt:
    • Wenn eine Funktion einen "try/except/catch"-Block enthält und während der Ausführung eine C++- oder OS/SEH-Exception ausgelöst wird, wird der Funktionsaufruf korrekt beendet, aber das Ergebnis ist undefiniert oder 0. In diesem Fall wird der interne Exception-Block nicht ausgeführt, weil die Exception direkt vom Debugger behandelt wird.
    • Wenn eine Funktion einen "try/except/catch"-Block enthält und keine Sprach- oder OS/SEH-Exceptions ausgelöst werden, wird der Funktionsaufruf ordnungsgemäß beendet und das Ergebnis ist – abhängig von der Funktion – korrekt.

Unterschiede beim Aufruf-Stack

Manche Werte werden eventuell bei der 64-Bit-Auswertung anders als bei der 32-Bit-Auswertung angezeigt. Beispielsweise wird der Aufruf-Stack ohne Funktionsparameter und Werte angezeigt.

Der Aufruf-Stack enthält normalerweise zwei Kopien von jedem Konstruktor und Destruktor. Der Aufruf-Stack könnte z.B. Folgendes enthalten:

 :0000000000401244 ; MyClass::~MyClass

 :0000000000401229 ; MyClass::~MyClass

 :0000000000401187 ; main

 :000000000040ef90 ; _startup
Hinweis: Clang implementiert das Itanium-ABI, das drei Konstruktoren und drei Destruktoren beschreibt, die sich nacheinander gegenseitig aufrufen. Clang implementiert aber nur zwei der drei Konstruktoren. Der dritte wird von C++Builder für Klassen im Delphi-Stil hinzugefügt. Siehe Itanium ABI doc oder diesen Beitrag:

http://stackoverflow.com/questions/6921295/dual-emission-of-constructor-symbols.}}

Reduzieren des Linker-Speicherverbrauchs mit Split DWARF

Hinweis: Das Feature "Split DWARF" wird nur unter C++ für Windows 64 Bit unterstützt. Dieses Feature reduziert die zu verarbeitende Datenmenge und reduziert daher Linker-Fehler im Linker. Weitere Informationen zum Umgang mit Linker-Fehlern finden Sie unter Behandeln von Linker-Fehlern aufgrund nicht ausreichendem Arbeitsspeicher.

In RAD Studio 10.4.2 wurde ein neues Feature eingeführt, um die zu verarbeitende Datenmenge zu reduzieren, insbesondere beim Linken von Anwendungen, die im Debug-Modus erstellt wurden. Dieses Feature, Split DWARF genannt, schreibt die Debug-Informationen in eine separate .dwo-Datei (DWARF-Objekt), die parallel zur normalen Objektdatei mit dem compilierten Code platziert wird. Der Linker verknüpft dann den ausführbaren Code mit nur wenigen anderen Informationen, was die Speicherbelastung reduziert.

Hinweis: Das Feature "Split DWARF" ist standardmäßig deaktiviert.

Aktivieren von Split DWARF in der IDE oder in MSBuild

Öffnen Sie das Dialogfeld "C++-Projektoptionen". Navigieren Sie zu "Erzeugen > C++-Compiler > Debuggen", und vergewissern Sie sich, dass "Zielplattform" auf eins der Windows-64-Bit-Ziele festgelegt ist.

  1. Aktivieren Sie das Kontrollkästchen "Split DWARF verwenden".
  2. Geben Sie in der Einstellung "DWO-Ausgabeverzeichnis" einen Ordner für die Debug-Informationsdateien an. Dies muss ein absoluter Pfad, kein relativer Pfad und kein Pfad mit Umgebungsvariablen sein.

Zum Beispiel ist c:\myproject\win64debug geeignet, aber ..\win64debug nicht.

Um dieses Feature zu deaktivieren, heben Sie die Markierung des Kontrollkästchens unter "Projektoptionen > Erzeugen > C++-Compiler > Debuggen" auf. Diese Einstellungen werden beim Erzeugen in der IDE oder beim Erzeugen mit MSBuild in der Befehlszeile verwendet.

Aktivieren von Split DWARF in der Befehlszeile

So aktivieren Sie Split DWARF manuell für ein reines Befehlszeilen-Build, z. B. eins, das BCC64 verwendet:

1. Geben Sie die Split DWARF-Einstellung in der Befehlszeile des Compilers an.

"-enable-split-dwarf"     
AND     
"-split-dwarf-file AFilename.dwo"     

Dadurch erstellt der Compiler die Datei AFilename.dwo und gibt den Speicherort dieser .dwo-Datei in der .o-Objektdatei aus. Beachten Sie, dass dieser Schritt noch nicht bedeutet, dass die .dwo-Datei die Debug-Informationen enthält.

2. Verwenden Sie "-dwo-dir <Verzeichnis>", um das Verzeichnis anzugeben, in das der Compiler die .dwo-Datei schreibt. Achten Sie darauf, dass es sich um einen absoluten Pfad handelt.

3. Führen Sie das Tool objcopy.exe für die .o-Datei aus. Durch diese Aktion werden alle DWARF-Abschnitte aus der normalen Objektdatei (.o) entfernt und in eine separate .dwo-Datei platziert. Dies muss für jede Objektdatei (.o) ausgeführt werden und muss mit dem in Schritt 1 angegebenen Namen übereinstimmen.

objcopy --split-dwo=AFilename.dwo AFilename.o 

4. Zum Schluss linken Sie die .o-Dateien, um Ihre EXE oder DLL wie gewohnt zu erstellen – dieser Schritt ist nicht geändert. Die Dateien sind kleiner als normal, da sie weniger Debug-Informationen enthalten. Jedes Objekt enthält den Namen und den Speicherort der .dwo-Datei. Wie in Schritt 2 beschrieben, ist dies der Speicherort für Ihren Computer und muss ein bestimmter absoluter Pfad sein.

Probleme beim Laden von Debug-Informationen bei Verwendung von Split DWARF

Bei der Verwendung von Split DWARF für das Debuggen unter Win64 kann es vorkommen, dass für Quelldateien, die sich nicht im selben Verzeichnis wie die Projektdatei befinden, falsche Verzeichnisinformationen in der Objektdatei generiert werden. Das bedeutet, dass Symbole aus diesen Dateien (Typen, lokale Variablen und Parameter) nicht verfügbar sind. Sie erkennen dies beim Debuggen daran, dass die blauen Punkte im Editor, die Zeilennummern angeben, sichtbar sind, und Sie einen Haltepunkt setzen können, aber keine Ausdrücke oder Symbole auswerten oder untersuchen können.

Um dies zu umgehen, geben Sie einen absoluten Pfad im Feld "DWO-Ausgabeverzeichnis" der Projektoption C++-Compiler > Debuggen > Split DWARF verwenden an oder die Befehlszeilenoption -dwo-dir, wenn Sie ein Build in der Befehlszeile erzeugen. Informationen zu diesen Einstellungen finden Sie oben.

Auswerten von Funktionsaufrufen wie strcmp()

Die Auswertung eines Funktionsaufrufs, wie strcmp(str, "ABC"), könnte einen Fehler wie den folgenden zurückgeben:

#include <system.hpp>
int main()
{ 
    char *str = "ABC";
    return strcmp(str, "ABC"); 
}

error: 'strcmp' has unknown return type; cast the call to its declared return type
error: 1 errors parsing expression

Sie müssen im Fenster Auswerten/Ändern den Rückgabetyp für strcmp() umwandeln:

   (int) strcmp(str, "ABC"); 

Siehe strcmp, _mbscmp, wcscmp.

Hinweis: Wenn Sie Probleme beim Debuggen haben, kann unser Support-Team Sie bitten, Debugger-Protokolle zur Verfügung zu stellen. Hier finden Sie Informationen dazu, wie Sie die Protokollierung für RAD Studio-Debugger aktivieren.

Siehe auch