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

In Chrome 92 haben wir den Memory Inspector eingeführt, ein Tool zur Überprüfung linearer Speicherpuffer. In diesem Artikel erfahren Sie, wie wir den Inspector für C/C++-Debugging verbessert haben und welche technischen Herausforderungen dabei auftreten.

Im Folgenden finden Sie einige relevante Blogposts für neue Nutzer des C/C++-Debugging und des Memory Inspector:

Einführung

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

Die Erkennung der Bytes Ihres Objekts im umgebenden WebAssembly-Speicher war ein Problem. Sie müssen die Größe des Objekts kennen und die Anzahl der Bytes ab dem Start des Objekts berücksichtigen. Im folgenden Screenshot ist das erste Byte eines int32-Arrays mit 10 Elementen ausgewählt. Es ist jedoch nicht sofort klar, welche anderen Byte 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 Memory Inspector mit einem einzelnen hervorgehobenen Byte

Objekthervorhebung im Memory Inspector

Ab Chrome 107 werden im Memory Inspector alle Byte eines C/C++-Speicherobjekts hervorgehoben. Dies hilft Ihnen, sie vom umgebenden Gedächtnis zu unterscheiden.

Screenshot des aktualisierten Memory Inspector mit einem leuchtend hervorgehobenen Array

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

Wenn Sie ein Byte außerhalb des untersuchten Objekts auswählen, wird die Hervorhebung deaktiviert, damit Sie nicht abgelenkt werden. Wenn Sie den Fokus wieder fokussieren möchten, klicken Sie noch einmal auf einen der 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 können Sie den Arbeitsspeicher Ihrer C/C++ Apps jetzt noch einfacher nutzen.

Möchtest du es ausprobieren? Erforderliche Schritte:

  • Sie benötigen Chrome 107 oder höher.
  • Installieren Sie die DWARF-Erweiterung für C/C++.
  • DWARF-Debugging in den DevTools aktivieren > Einstellungen. Einstellungen > Tests > WebAssemble-Debugging: DWARF-Unterstützung aktivieren
  • Öffnen Sie diese Demoseite.
  • Folgen Sie der Anleitung auf der Seite.

Debugging-Beispiel

In diesem Abschnitt wird anhand eines Spielzeugfehlers veranschaulicht, wie Sie den Memory Inspector für das C/C++-Debugging verwenden können. Im Codebeispiel unten erstellt ein Programmierer ein Ganzzahlarray und entscheidet sich, das letzte Element mithilfe der Zeigerarithmetik auszuwählen. Leider hat der Programmierer einen Fehler bei der Zeigerberechnung gemacht und jetzt gibt das Programm nicht das letzte Element aus, sondern druckt unsinnige Werte 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 ruft den Memory Inspector auf, um das Problem zu beheben. Weitere Informationen findest du in dieser Demo. Zuerst überprüft er das Array im Memory Inspector und stellt fest, dass das numbers-Array wie erwartet nur die Ganzzahlen 1, 2, 3 und 4 enthält.

Screenshot des geöffneten Memory Inspector mit einem überprüften int32-Array. Alle Array-Elemente sind markiert.

Als Nächstes wird die Variable lastNumber im Bereich Scope (Umfang) angezeigt. Der Zeiger zeigt auf eine Ganzzahl außerhalb des Arrays. Mit diesem Wissen erkennt der Programmierer, dass er den Zeigerversatz bei Zeile 8 falsch gezählt hat. Es hätte ptr + arraySize - 1 sein sollen.

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

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

So ermittelt die Entwicklertools, was hervorgehoben werden sollte

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

Um die volle Leistung des C/C++-Debugging in den Entwicklertools nutzen zu können, benötigen Sie zwei Dinge:

  • In Chrome installierte DWARF-Erweiterung für C/C++
  • 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, ist nicht in der Lage, C oder C++ auszuführen. Dank Emscripten, einem Compiler aus C/C++ für WebAssembly, können Sie in C oder C++ als WebAssembly erstellte Apps kompilieren und im Browser ausführen.

Während der Kompilierung bettet emscripten DWARF-Debug-Daten in Ihr Binärprogramm ein. Auf übergeordneter Ebene helfen diese Daten der Erweiterung zu ermitteln, welche WebAssembly-Variablen Ihren C/C++-Variablen entsprechen, und vieles mehr. Auf diese Weise können Ihnen DevTools Ihre C++-Variablen anzeigen, obwohl V8 tatsächlich WebAssembly ausführt. In diesem Blogpost finden Sie ein Beispiel für DWARF-Debug-Daten.

Was passiert also, wenn du die lastNumber aufdeckst? Sobald Sie auf das Speichersymbol klicken, prüft die Entwicklertools, welche Variable Sie untersuchen möchten. Anschließend fragt es die Erweiterung nach dem Datentyp und dem Speicherort von lastNumber ab. Sobald die Erweiterung mit diesen Informationen antwortet, kann der Memory Inspector das relevante Speichersegment anzeigen und den Typ kennen und dir auch die Größe des Objekts anzeigen.

Wenn Sie sich lastNumber im vorherigen Beispiel ansehen, stellen Sie vielleicht fest, dass wir lastNumber: int * geprüft haben, aber der Chip im Memory Inspector *lastNumber: int lautet. Woran liegt das? Das Prüftool verwendet die Zeiger-Dereferenzierung im C++-Stil, um den Typ des angezeigten Objekts anzugeben. Wenn Sie einen Zeiger prüfen, zeigt das Prüftool an, worauf er zeigt.

Highlights in Debugger-Schritten beibehalten

Wenn Sie im Memory Inspector ein Objekt aufdecken und den Debugger verwenden, wird die Markierung beibehalten, sofern sie der Meinung ist, dass sie noch anwendbar ist. Anfangs war diese Funktion noch nicht in unserer Roadmap enthalten, aber wir haben schnell festgestellt, dass dies Ihre Debugging-Erfahrung kompromittiert. Stellen Sie sich vor, Sie müssen das Array nach jedem Schritt wie im folgenden Video noch einmal überprüfen.

Wenn der Debugger einen neuen Haltepunkt erreicht, fragt der Memory Inspector noch einmal V8 und die Erweiterung nach der Variablen ab, die mit der vorherigen Markierung verknüpft ist. Anschließend werden die Positionen und Typen der Objekte verglichen. Stimmen sie überein, bleibt die Markierung erhalten. Im obigen Video schreibt eine For-Schleife in das Array x. Diese Vorgänge ändern nicht den Typ oder die Position des Arrays, sodass es hervorgehoben bleibt.

Sie fragen sich vielleicht, welche Auswirkungen das auf Cursor hat. Wenn Sie einen markierten Zeiger haben und ihn einem anderen Objekt neu zuweisen, unterscheiden sich die alten und neuen Positionen der markierten Objekte und die Markierung verschwindet. Da sich das neue 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 Zeiger noch einmal markieren, indem Sie im Bereich Scope (Bereich) auf das Speichersymbol klicken.

Fazit

In diesem Artikel werden unsere Verbesserungen am Memory Inspector für die Fehlerbehebung in C/C++ beschrieben. Wir hoffen, dass die neuen Funktionen das Debugging im Arbeitsspeicher Ihrer C/C++ Apps vereinfachen werden. Wenn du Verbesserungsvorschläge hast, kannst du den Programmfehler melden.

Weiteres Vorgehen

Weitere Informationen erhalten Sie unter: