In Chrome 92 haben wir den Speicher-Inspector eingeführt, ein Tool zum Prüfen von linearen Arbeitsspeicherpuffern. In diesem Artikel erfahren Sie, wie wir den Inspector für das C/C++-Debugging verbessert haben und welche technischen Herausforderungen dabei aufgetreten sind.
Hier sind einige relevante Blogbeiträge, wenn Sie neu im C/C++-Debugging und im Memory Inspector sind:
- Interessieren Sie sich für die detaillierte Speicherfehlerbehebung? Weitere Informationen finden Sie unter Einführung in den Arbeitsspeicher-Prüftool.
- Möchten Sie eine Einführung in die gesamte C/C++-Fehlerbehebungssuite erhalten? Weitere Informationen finden Sie unter WASM mit modernen Tools debuggen und Schnelles WebAssembly-Debugging.
Einführung
Der Memory Inspector bietet Ihnen leistungsstärkere Optionen zur Fehlerbehebung für lineare Arbeitsspeicher-Puffer. Bei C/C++ können Sie C/C++-Speicherobjekte im WebAssembly-Speicher prüfen.
Es war schwierig, die Bytes des Objekts im umgebenden WebAssembly-Speicher zu erkennen. Sie müssen die Größe des Objekts kennen und die Anzahl der Bytes vom Anfang des Objekts zählen. Im folgenden Screenshot ist 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 sofort alle Bytes erkennen könnten, die zum Objekt gehören?
Hervorhebung von Objekten im Arbeitsspeicher-Prüftool
Ab Chrome 107 werden im Speicher-Inspector alle Bytes eines C/C++-Speicherobjekts hervorgehoben. So können Sie sie von der umgebenden Erinnerung unterscheiden.
Im Video unten sehen Sie den Memory Inspector in Aktion. Wenn Sie das Array x
im Arbeitsspeicher-Prüftool anzeigen, wird in der Arbeitsspeicheranzeige der markierte Arbeitsspeicher zusammen mit einem neuen Chip direkt darüber angezeigt. Dieser Chip erinnert Sie an den Namen und den Typ des markierten Arbeitsspeichers. Klicken Sie auf den Chip, um zum Arbeitsspeicher des Objekts zu gelangen. Wenn Sie den Mauszeiger auf den Chip bewegen, wird ein Kreuzsymbol angezeigt. Klicken Sie darauf, um die Markierung aufzuheben.
Wenn Sie ein Byte außerhalb des zu prüfenden Objekts auswählen, wird die Markierung unscharf, um Ablenkungen zu vermeiden. Wenn Sie den Fokus wieder auf das Objekt legen möchten, klicken Sie noch einmal auf einen der Bytes des Objekts oder auf den Chip.
Die Unterstützung für die Objekthervorhebung ist nicht auf Arrays beschränkt. Sie können auch Strukturen, Objekte und Zeiger prüfen. Durch diese Änderungen ist die Untersuchung des Arbeitsspeichers Ihrer C/C++-Anwendungen jetzt noch einfacher.
Möchten Sie es ausprobieren? Folgende Voraussetzungen müssen erfüllt sein:
- Sie verwenden Chrome 107 oder höher.
- Installieren Sie die C/C++-DWARF-Erweiterung.
- Aktivieren Sie das DWARF-Debugging unter DevTools > Einstellungen > Experimente > WebAssemble-Debugging: DWARF-Unterstützung aktivieren.
- Öffnen Sie diese Demoseite.
- Folgen Sie der Anleitung auf der Seite.
Beispiel für das Debugging
In diesem Abschnitt sehen wir uns ein Beispiel für einen einfachen Fehler an, um zu veranschaulichen, wie Sie den Memory Inspector für das C/C++-Debugging verwenden können. Im folgenden Codebeispiel erstellt ein Programmierer ein Ganzzahl-Array und entscheidet sich, das letzte Element mithilfe der Pointerarithmetik auszuwählen. Leider hat der Programmierer bei der Zeigerberechnung einen Fehler gemacht. Anstatt 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 wendet sich an den Memory Inspector, um das Problem zu beheben. In dieser Demo zeigen wir dir, wie es geht. Er prüft zuerst das Array im Speicher-Inspector und stellt fest, dass das Array numbers
wie erwartet nur die Ganzzahlen 1
, 2
, 3
und 4
enthält.
Als Nächstes blendet er die Variable lastNumber
aus dem Bereich Scope ein und stellt fest, dass der Zeiger auf eine Ganzzahl außerhalb des Arrays zeigt. Mit diesem Wissen erkennt der Programmierer, dass er den Zeigeroffset in Zeile 8 falsch gezählt hat. Es sollte ptr + arraySize - 1
sein.
Obwohl dies ein einfaches Beispiel ist, veranschaulicht es, wie die Objektmarkierung die Größe und Position von Speicherobjekten effektiv vermittelt. So können Sie besser nachvollziehen, was im Arbeitsspeicher Ihrer C/C++-Anwendung passiert.
So ermittelt DevTools, was hervorgehoben werden soll
In diesem Abschnitt sehen wir uns die Tools an, mit denen das C/C++-Debugging möglich ist. Insbesondere erfahren Sie, wie die DevTools, V8, die C/C++-DWARF-Erweiterung und Emscripten das C/C++-Debugging in Chrome ermöglichen.
Damit Sie das C/C++-Debugging in den Entwicklertools in vollem Umfang nutzen können, sind zwei Dinge erforderlich:
- Die in Chrome installierte C/C++-DWARF-Erweiterung
- C/C++-Quelldateien, die mit dem neuesten Emscripten-Compiler gemäß der Anleitung in diesem Blogpost in WebAssembly kompiliert wurden
Aber warum? V8 , die JavaScript- und WebAssembly-Engine von Chrome, kann C oder C++ nicht ausführen. Mit Emscripten, einem C/C++-zu-WebAssembly-Compiler, können Sie in C oder C++ geschriebene Apps als WebAssembly kompilieren und im Browser ausführen.
Während der Kompilierung bettet emscripten DWARF-Debugdaten in Ihre Binärdatei ein. Diese Daten helfen der Erweiterung unter anderem, herauszufinden, welche WebAssembly-Variablen Ihren C/C++-Variablen entsprechen. So können Ihnen die DevTools Ihre C++-Variablen anzeigen, obwohl in V8 tatsächlich WebAssembly ausgeführt wird. In diesem Blogpost finden Sie ein Beispiel für DWARF-Debugdaten.
Was passiert also, wenn Sie die lastNumber
enthüllen? Sobald Sie auf das Speichersymbol klicken, wird in DevTools geprüft, welche Variable Sie prüfen möchten. Anschließend wird die Erweiterung über den Datentyp und den Speicherort von lastNumber
abgefragt. Sobald die Erweiterung mit diesen Informationen antwortet, kann der Speicher-Inspector den entsprechenden Speicherbereich anzeigen und anhand des Typs auch die Größe des Objekts.
Wenn Sie sich lastNumber
im vorherigen Beispiel ansehen, stellen Sie möglicherweise fest, dass wir lastNumber: int *
geprüft haben, der Chip im Speicher-Inspector aber *lastNumber: int
anzeigt. Was ist da los? Der Inspector verwendet die C++-Methode zur Dereferenzierung von Pointern, um den Typ des angezeigten Objekts anzugeben. Wenn Sie einen Verweis prüfen, sehen Sie im Inspektor, worauf er verweist.
Hervorgehobene Schritte im Debugger beibehalten
Wenn Sie ein Objekt im Arbeitsspeicher-Prüftool anzeigen und mit dem Debugger einen Schritt ausführen, behält das Prüftool die Markierung bei, wenn es der Meinung ist, dass sie noch relevant ist. Diese Funktion war ursprünglich nicht in unserer Roadmap enthalten, aber wir haben schnell erkannt, dass sie die Fehlerbehebung erschwert. Stellen Sie sich vor, Sie müssten das Array nach jedem Schritt noch einmal prüfen, wie im Video unten.
Wenn der Debugger einen neuen Haltepunkt erreicht, fragt der Speicher-Inspektor noch einmal V8 und die Erweiterung nach der Variablen ab, die mit dem vorherigen Highlight verknüpft ist. Anschließend werden die Standorte und Typen der Objekte verglichen. Wenn sie übereinstimmen, bleibt die Markierung erhalten. Im obigen Video wird mit einer For-Schleife in das Array x
geschrieben. Diese Vorgänge ändern weder den Typ noch die Position des Arrays, sodass es weiterhin hervorgehoben bleibt.
Sie fragen sich vielleicht, wie sich das auf Zeiger auswirkt. Wenn Sie einen markierten Cursor haben und ihn einem anderen Objekt zuweisen, unterscheiden sich die alte und die neue Position der markierten Objekte und die Markierung verschwindet. Da das neu aufgelöste Objekt überall im WebAssembly-Speicher abgelegt werden kann und wahrscheinlich wenig Bezug zum vorherigen Speicherort hat, ist es übersichtlicher, die Markierung zu entfernen, als zu einem neuen Speicherort zu springen. Sie können den Cursor wieder hervorheben, indem Sie im Bereich Scope auf das zugehörige Speichersymbol 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 Ihrer C/C++-Anwendungen vereinfachen. Wenn du Verbesserungsvorschläge hast, reiche bitte einen Fehlerbericht ein.
Weiteres Vorgehen
Weitere Informationen erhalten Sie unter: