Memory Inspector für C/C++-Debugging erweitern

In Chrome 92 haben wir den Memory Inspector eingeführt, ein Tool zur Überprüfung linearer Speicherzwischenspeicher. In diesem Artikel besprechen wir, wie wir den Inspector für das Debugging in C/C++ verbessert haben und welche technischen Herausforderungen dabei aufgetreten sind.

Hier finden Sie einige relevante Blogposts, wenn Sie mit C/C++-Debugging und dem Memory Inspector noch nicht vertraut sind:

Einleitung

Der Memory Inspector bietet leistungsfähigere Debugging-Optionen für lineare Arbeitsspeicherzwischenspeicher. Bei C/C++ können Sie C/C++ Speicherobjekte im WebAssembly-Speicher prüfen.

Die Erkennung der Objektbyte im umgebenden WebAssembly-Speicher war ein Problem. Sie müssen die Größe des Objekts ab Beginn des Objekts kennen und die Anzahl der Byte kennen. Im folgenden Screenshot wird das erste Byte eines int32-Arrays mit 10 Elementen ausgewählt. Es ist jedoch nicht sofort ersichtlich, welche anderen Bytes zum Array gehören. Wäre es nicht schön, wenn Sie alle Bytes, die zum Objekt gehören, sofort erkennen könnten?

Screenshot des ursprünglichen Arbeitsspeicher-Inspectors mit einem einzelnen hervorgehobenen Byte

Objekthervorhebung im Memory Inspector

Ab Chrome 107 hebt der Memory Inspector alle Bytes eines C/C++-Speicherobjekts hervor. So kannst du sie vom umgebenden Gedächtnis unterscheiden.

Screenshot des aktualisierten Arbeitsspeicherprüftools mit einem farbig hervorgehobenen Array

Im folgenden Video sehen Sie den Memory Inspector in Aktion. Wenn Sie im Memory Inspector das Array x anzeigen, wird im Memory Viewer der hervorgehobene Arbeitsspeicher zusammen mit einem neuen Chip direkt darüber angezeigt. Dieser Chip erinnert dich an den Namen und den Typ der markierten Erinnerung. Klicken Sie auf den Chip, um zum Arbeitsspeicher des Objekts zu springen. Wenn Sie den Mauszeiger auf den Chip bewegen, wird ein Kreuz angezeigt. Klicken Sie darauf, um die Markierung zu entfernen.

Wenn Sie ein Byte außerhalb des zu untersuchenden Objekts auswählen, wird die Markierung defokussiert, damit Sie nicht abgelenkt werden. Wenn Sie es wieder scharf stellen möchten, klicken Sie noch einmal auf ein Byte des Objekts oder auf den Chip.

Die Unterstützung der Objekthervorhebung ist nicht auf Arrays beschränkt. Sie können auch Strukturen, Objekte und Zeiger überprüfen. Dank dieser Änderungen ist es jetzt einfacher denn je, den Arbeitsspeicher Ihrer C-/C++-Apps zu erkunden.

Möchtest du es ausprobieren? Erforderliche Schritte:

  • Sie benötigen Chrome 107 oder höher.
  • Installieren Sie die DWARF-Erweiterung C/C++.
  • Aktivieren Sie die DWARF-Fehlerbehebung unter DevTools > Einstellungen. DevTools > DevTools > DevTools.
  • Öffnen Sie diese Demoseite.
  • Folgen Sie der Anleitung auf der Seite.

Beispiel für die Fehlerbehebung

In diesem Abschnitt wird anhand eines Spielzeugfehlers veranschaulicht, wie Sie den Memory Inspector für das Debugging in C/C++ verwenden können. Im folgenden Codebeispiel erstellt ein Programmierer ein Ganzzahlarray und entscheidet sich, das letzte Element mithilfe der Zeigerarithmetik auszuwählen. Leider ist dem Programmierer bei der Zeigerberechnung ein Fehler unterlaufen. Statt das letzte Element auszugeben, druckt das Programm jetzt Unsinnswerte aus.

#include <iostream>

int main()
{
    int numbers[] = {1, 2, 3, 4};
    int *ptr = numbers;
    int arraySize = sizeof(numbers)/sizeof(int);
    int* lastNumber = ptr + arraySize;  // Can you notice the bug here?
    std::cout <<../ *lastNumber <<../ '\n';
    return 0;
}

Der Programmierer verwendet den Memory Inspector, um das Problem zu beheben. Weitere Informationen dazu finden Sie in dieser Demo. Zuerst wird das Array im Memory Inspector geprüft. Dabei stellt er fest, dass das numbers-Array wie erwartet nur die Ganzzahlen 1, 2, 3 und 4 enthält.

Screenshot des geöffneten Speicherinspektors mit einem geprüften int32-Array. Alle Array-Elemente sind markiert.

Als Nächstes wird die Variable lastNumber aus dem Bereich Scope (Bereich) sichtbar und der Zeiger verweist auf eine Ganzzahl außerhalb des Arrays. Mit diesem Wissen stellt der Programmierer fest, dass er die Zeigerversatz bei Zeile 8 falsch gezählt hat. Es hätte ptr + arraySize - 1 lauten müssen.

Screenshot des geöffneten Speicherinspektors mit dem hervorgehobenen Speicher, auf den ein Zeiger namens „lastNumber“ verweist. Der hervorgehobene Arbeitsspeicher liegt direkt nach dem letzten Byte des zuvor hervorgehobenen Arrays.

Es handelt sich zwar um ein Spielzeugbeispiel, aber es zeigt, wie die Objekthervorhebung effektiv die Größe und Position von Speicherobjekten vermittelt, was Ihnen helfen kann, besser zu verstehen, was im Speicher Ihrer C/C++ App passiert.

Wie die Entwicklertools herausgefunden haben, was hervorgehoben werden sollte

In diesem Abschnitt werfen wir einen Blick auf die verschiedenen Tools, die das C/C++-Debugging ermöglichen. Sie erfahren, wie die Entwicklertools, V8, die C/C++ DWARF-Erweiterung und Emscripten das C/C++-Debugging in Chrome ermöglichen.

Um das volle Potenzial des C/C++-Debugging in den Entwicklertools auszuschöpfen, benötigen Sie zwei Dinge:

  • Die in Chrome installierte C/C++ DWARF-Erweiterung
  • C/C++-Quelldateien, die mit dem neuesten Emscripten-Compiler in WebAssembly kompiliert wurden, wie in diesem Blogpost beschrieben.

Aber warum? V8, die JavaScript- und WebAssembly-Engine von Chrome, weiß nicht, wie man C oder C++ ausführt. Dank Emscripten, einem Compiler für C/C++ zu WebAssembly, kannst du Apps, die in C oder C++ als WebAssembly erstellt wurden, kompilieren und im Browser ausführen.

Während der Kompilierung bettet Emscripten DWARF-Debug-Daten in Ihre Binärdatei ein. Auf übergeordneter Ebene helfen diese Daten der Erweiterung, herauszufinden, welche WebAssembly-Variablen Ihren C/C++-Variablen entsprechen und vieles mehr. So können die Entwicklertools Ihre C++-Variablen anzeigen, auch wenn WebAssembly in V8 ausgeführt wird. In diesem Blogpost finden Sie ein Beispiel für DWARF-Debug-Daten.

Was passiert also eigentlich, wenn du lastNumber enthüllst? Sobald Sie auf das Speichersymbol klicken, prüfen die Entwicklertools, welche Variable Sie untersuchen möchten. Anschließend werden bei der Erweiterung der Datentyp und der Standort von lastNumber abgefragt. Sobald die Erweiterung mit dieser Information antwortet, kann der Memory Inspector das entsprechende Speichersegment anzeigen und seinen Typ kennen sowie die Größe des Objekts anzeigen.

Wenn Sie sich im vorherigen Beispiel lastNumber ansehen, werden Sie vielleicht feststellen, dass wir lastNumber: int * geprüft haben. Der Chip im Memory Inspector zeigt jedoch *lastNumber: int an. Woran liegt das? Der Inspector verwendet Zeiger-Ableitungen im C++-Stil, um den Typ des angezeigten Objekts anzugeben. Wenn Sie einen Zeiger untersuchen, zeigt er Ihnen, worauf er verweist.

Markierungen bei Debugger-Schritten beibehalten

Wenn Sie ein Objekt im Memory Inspector aufdecken und einen Schritt mit dem Debugger ausführen, behält der Inspector die Markierung bei, sofern er denkt, dass sie noch anwendbar ist. Anfangs hatten wir diese Funktion noch nicht auf unserer Roadmap, aber wir haben schnell gemerkt, dass dies Ihre Erfahrung mit der Fehlerbehebung beeinträchtigt. Stellen Sie sich vor, Sie müssten das Array nach jedem Schritt neu überprüfen, wie im Video unten gezeigt.

Wenn der Debugger einen neuen Haltepunkt erreicht, fragt der Memory Inspector erneut V8 und die Erweiterung für die Variable ab, die der vorherigen Markierung zugeordnet ist. Dann werden die Positionen und Typen der Objekte verglichen. Bei Übereinstimmung bleibt die Markierung bestehen. Im Video oben wird eine for-Schleife in das Array x geschrieben. Diese Vorgänge ändern nicht den Typ oder die Position des Arrays, sodass es weiterhin hervorgehoben bleibt.

Sie fragen sich vielleicht, wie sich das auf die Verweise auswirkt. Wenn Sie einen hervorgehobenen Cursor einem anderen Objekt zuweisen, unterscheiden sich die alten und neuen Positionen der markierten Objekte und die Markierung verschwindet. Da sich das neu verweisende Objekt an einer beliebigen Stelle im WebAssembly-Speicher befinden kann und wahrscheinlich wenig Bezug zum vorherigen Speicherort hat, ist das Entfernen der Markierung deutlicher als das Wechseln zu einem neuen Speicherort. Sie können den Mauszeiger noch einmal hervorheben, indem Sie auf sein Speichersymbol im Bereich Bereich klicken.

Fazit

In diesem Artikel wurden die Verbesserungen am Memory Inspector für das C/C++-Debugging beschrieben. Wir hoffen, dass die neuen Funktionen das Debuggen des Arbeitsspeichers in C/C++ Apps vereinfachen werden. Wenn Sie Vorschläge zur weiteren Verbesserung haben, melden Sie uns den Fehler.

Weiteres Vorgehen

Weitere Informationen erhalten Sie unter: