Uitbreiding van de Memory Inspector voor foutopsporing in C/C++

In Chrome 92 hebben we de Memory Inspector geïntroduceerd, een hulpmiddel voor het inspecteren van lineaire geheugenbuffers. In dit artikel bespreken we hoe we de Inspector voor C/C++-foutopsporing hebben verbeterd en welke technische uitdagingen we onderweg tegenkomen.

Dit zijn een paar relevante blogposts als u nieuw bent bij het debuggen van C/C++ en de Memory Inspector :

Invoering

De Memory Inspector biedt u krachtigere foutopsporingsopties voor lineaire geheugenbuffers. In het geval van C/C++ kunt u C/C++-geheugenobjecten inspecteren in het WebAssembly Memory.

Het herkennen van de bytes van uw object in het omringende WebAssembly-geheugen was een pijnpunt. U moet de grootte van het object kennen en het aantal bytes vanaf het begin van het object kennen. In de onderstaande schermafbeelding is de eerste byte van een int32 -array met 10 elementen geselecteerd, maar het is niet meteen duidelijk welke andere bytes tot de array behoren. Zou het niet mooi zijn als je meteen alle bytes zou kunnen herkennen die bij het object horen?

Schermafbeelding van de oorspronkelijke geheugeninspecteur met een enkele gemarkeerde byte

Objectmarkering in de Memory Inspector

Vanaf Chrome 107 markeert de Memory Inspector alle bytes van een C/C++-geheugenobject. Dit helpt je ze te onderscheiden van het omringende geheugen.

Schermafbeelding van de bijgewerkte geheugeninspecteur met een levendig gemarkeerde array

Bekijk de onderstaande video om de Memory Inspector in actie te zien. Terwijl je de array x in de Memory Inspector onthult, verschijnt het gemarkeerde geheugen in de Memory Viewer, samen met een nieuwe chip er vlak boven. Deze chip herinnert u de naam en het type van het gemarkeerde geheugen. Klik op de chip om naar het geheugen van het object te springen. Als u over de chip beweegt, verschijnt er een kruispictogram. Klik erop om de markering te verwijderen.

Wanneer u een byte selecteert buiten het object dat u inspecteert, wordt de markering onscherp om te voorkomen dat u wordt afgeleid. Om het opnieuw scherp te stellen, klikt u opnieuw op een van de bytes van het object of op de chip.

De ondersteuning voor het markeren van objecten is niet beperkt tot arrays. U kunt ook structuren, objecten en verwijzingen inspecteren. Deze wijzigingen maken het verkennen van het geheugen van uw C/C++-apps eenvoudiger dan ooit!

Wil je het eens proberen? U moet:

  • Heb Chrome 107 of nieuwer.
  • Installeer de C/C++ DWARF-extensie.
  • Schakel DWARF-foutopsporing in DevTools > in Instellingen. Instellingen > Experimenten > WebAssemble-foutopsporing: DWARF-ondersteuning inschakelen .
  • Open deze demopagina .
  • Volg de instructies op de pagina.

Voorbeeld van foutopsporing

Laten we in deze sectie een speelgoedbug bekijken om te illustreren hoe u de Memory Inspector kunt gebruiken voor foutopsporing in C/C++. In het onderstaande codevoorbeeld maakt een programmeur een integer-array en besluit pointer-berekeningen te gebruiken om het laatste element te selecteren. Helaas heeft de programmeur een fout gemaakt bij de pointerberekening, en in plaats van het laatste element af te drukken, drukt het programma nu onzinwaarden af.

#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;
}

De programmeur wendt zich tot de Memory Inspector om het probleem op te lossen. Je kunt deze demo volgen! Ze inspecteren eerst de array in Memory Inspector en zien dat de numbers alleen de gehele getallen 1 , 2 , 3 en 4 bevat, zoals verwacht.

Schermafbeelding van geopende geheugeninspecteur met een geïnspecteerde int32-array. Alle array-elementen zijn gemarkeerd.

Vervolgens onthullen ze de lastNumber variabele uit het Scope -paneel en merken ze dat de aanwijzer naar een geheel getal buiten de array wijst! Uitgerust met deze kennis realiseert de programmeur zich dat ze de pointer-offset op regel 8 verkeerd hebben geteld. Het had ptr + arraySize - 1 moeten zijn.

Schermafbeelding van geopende geheugeninspecteur met gemarkeerd geheugen waarnaar wordt verwezen door een aanwijzer met de naam 'lastNumber'. Het gemarkeerde geheugen ligt direct na de laatste byte van de eerder gemarkeerde array.

Hoewel dit een speelgoedvoorbeeld is, illustreert het hoe objectaccentuering effectief de grootte en positie van geheugenobjecten overbrengt, waardoor u beter kunt begrijpen wat er in het geheugen van uw C/C++-app gebeurt.

Hoe DevTools uitzoekt wat moet worden benadrukt

In deze sectie bekijken we het ecosysteem van tools die foutopsporing in C/C++ mogelijk maken. Meer specifiek leer je hoe DevTools, V8, de C/C++ DWARF-extensie en Emscripten C/C++-foutopsporing in Chrome mogelijk maken.

Om de volledige kracht van C/C++-foutopsporing in DevTools te benutten, hebt u twee dingen nodig:

  • De C/C++ DWARF-extensie geïnstalleerd in Chrome
  • C/C++-bronbestanden gecompileerd naar WebAssembly met de nieuwste Emscripten-compiler, zoals aangegeven in deze blogpost

Maar waarom? V8 , de JavaScript- en WebAssembly-engine van Chrome, weet niet hoe C of C++ moet worden uitgevoerd. Dankzij Emscripten , een C/C++ naar WebAssembly-compiler, kunt u apps die in C of C++ zijn gebouwd, compileren als WebAssembly en deze in de browser uitvoeren!

Tijdens het compileren zal emscripten DWARF-foutopsporingsgegevens in uw binaire bestand insluiten. Op een hoog niveau helpen deze gegevens de extensie om erachter te komen welke WebAssembly-variabelen overeenkomen met uw C/C++-variabelen, en meer. Op deze manier kan DevTools u uw C++-variabelen laten zien, ondanks dat V8 daadwerkelijk WebAssembly draait. Als je nieuwsgierig bent, bekijk dan deze blogpost voor een voorbeeld van DWARF-foutopsporingsgegevens.

Dus wat gebeurt er eigenlijk als je het lastNumber onthult? Zodra u op het geheugenpictogram klikt, controleert DevTools welke variabele u wilt inspecteren. Vervolgens wordt de extensie opgevraagd over het gegevenstype en de locatie van lastNumber . Zodra de extensie met die informatie reageert, kan de Memory Inspector het relevante stukje geheugen weergeven en het type kennen, en ook de grootte van het object.

Als je in het eerdere voorbeeld naar lastNumber kijkt, merk je misschien dat we lastNumber: int * hebben geïnspecteerd, maar de chip in de Memory Inspector zegt *lastNumber: int , wat geeft dit? De inspecteur gebruikt pointer-dereferentie in C++-stijl om het type object aan te geven dat u wordt getoond! Als u een aanwijzer inspecteert, zal de inspecteur u laten zien waarnaar deze verwijst.

Aanhoudende hoogtepunten van debugger-stappen

Wanneer u een object in de Memory Inspector onthult en met de debugger stapt, blijft de Inspector de markering behouden als hij denkt dat deze nog steeds van toepassing is. In eerste instantie hadden we deze functie niet op onze routekaart staan, maar we realiseerden ons al snel dat dit uw foutopsporingservaring in gevaar brengt. Stel je voor dat je de array na elke stap opnieuw moet inspecteren, zoals in de onderstaande video!

Wanneer de debugger een nieuw breekpunt tegenkomt, vraagt ​​de Memory Inspector opnieuw naar V8 en de extensie voor de variabele die aan de vorige highlight is gekoppeld. Vervolgens vergelijkt het de locaties en typen van de objecten. Als ze overeenkomen, blijft het hoogtepunt bestaan. In de video hierboven is er een for-loop die naar de array x schrijft. Deze bewerkingen veranderen het type of de positie van de array niet, dus deze blijft gemarkeerd.

Je vraagt ​​je misschien af ​​welke invloed dit heeft op de pointers. Als u een gemarkeerde aanwijzer hebt en deze opnieuw aan een ander object toewijst, verschillen de oude en nieuwe posities van de gemarkeerde objecten en verdwijnt de markering. Omdat het nieuw aangewezen object overal in het WebAssembly-geheugen kan voorkomen en waarschijnlijk weinig relatie zal hebben met de vorige geheugenlocatie, is het verwijderen van de markering duidelijker dan naar een nieuwe geheugenlocatie springen. U kunt de aanwijzer opnieuw markeren door op het geheugenpictogram in het bereikvenster te klikken.

Conclusie

In dit artikel worden onze verbeteringen aan de Memory Inspector voor foutopsporing in C/C++ beschreven. We hopen dat de nieuwe functies het debuggen van het geheugen van uw C/C++-apps zullen vereenvoudigen! Als je suggesties hebt om het verder te verbeteren, laat het ons dan weten door een bug in te dienen !

Wat is het volgende

Voor meer informatie, zie:

,

In Chrome 92 hebben we de Memory Inspector geïntroduceerd, een hulpmiddel voor het inspecteren van lineaire geheugenbuffers. In dit artikel bespreken we hoe we de Inspector voor C/C++-foutopsporing hebben verbeterd en welke technische uitdagingen we onderweg tegenkomen.

Dit zijn een paar relevante blogposts als u nieuw bent bij het debuggen van C/C++ en de Memory Inspector :

Invoering

De Memory Inspector biedt u krachtigere foutopsporingsopties voor lineaire geheugenbuffers. In het geval van C/C++ kunt u C/C++-geheugenobjecten inspecteren in het WebAssembly Memory.

Het herkennen van de bytes van uw object in het omringende WebAssembly-geheugen was een pijnpunt. U moet de grootte van het object kennen en het aantal bytes vanaf het begin van het object kennen. In de onderstaande schermafbeelding is de eerste byte van een int32 -array met 10 elementen geselecteerd, maar het is niet meteen duidelijk welke andere bytes tot de array behoren. Zou het niet mooi zijn als je meteen alle bytes zou kunnen herkennen die bij het object horen?

Schermafbeelding van de oorspronkelijke geheugeninspecteur met een enkele gemarkeerde byte

Objectmarkering in de Memory Inspector

Vanaf Chrome 107 markeert de Memory Inspector alle bytes van een C/C++-geheugenobject. Dit helpt je ze te onderscheiden van het omringende geheugen.

Schermafbeelding van de bijgewerkte geheugeninspecteur met een levendig gemarkeerde array

Bekijk de onderstaande video om de Memory Inspector in actie te zien. Terwijl je de array x in de Memory Inspector onthult, verschijnt het gemarkeerde geheugen in de Memory Viewer, samen met een nieuwe chip er vlak boven. Deze chip herinnert u de naam en het type van het gemarkeerde geheugen. Klik op de chip om naar het geheugen van het object te springen. Als u over de chip beweegt, verschijnt er een kruispictogram. Klik erop om de markering te verwijderen.

Wanneer u een byte selecteert buiten het object dat u inspecteert, wordt de markering onscherp om te voorkomen dat u wordt afgeleid. Om het opnieuw scherp te stellen, klikt u opnieuw op een van de bytes van het object of op de chip.

De ondersteuning voor het markeren van objecten is niet beperkt tot arrays. U kunt ook structuren, objecten en verwijzingen inspecteren. Deze wijzigingen maken het verkennen van het geheugen van uw C/C++-apps eenvoudiger dan ooit!

Wil je het eens proberen? U moet:

  • Heb Chrome 107 of nieuwer.
  • Installeer de C/C++ DWARF-extensie.
  • Schakel DWARF-foutopsporing in DevTools > in Instellingen. Instellingen > Experimenten > WebAssemble-foutopsporing: DWARF-ondersteuning inschakelen .
  • Open deze demopagina .
  • Volg de instructies op de pagina.

Voorbeeld van foutopsporing

Laten we in deze sectie een speelgoedbug bekijken om te illustreren hoe u de Memory Inspector kunt gebruiken voor foutopsporing in C/C++. In het onderstaande codevoorbeeld maakt een programmeur een integer-array en besluit pointer-berekeningen te gebruiken om het laatste element te selecteren. Helaas heeft de programmeur een fout gemaakt bij het berekenen van de pointer, en in plaats van het laatste element af te drukken, drukt het programma nu onzinwaarden af.

#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;
}

De programmeur wendt zich tot de Memory Inspector om het probleem op te lossen. Je kunt deze demo volgen! Ze inspecteren eerst de array in Memory Inspector en zien dat de numbers alleen de gehele getallen 1 , 2 , 3 en 4 bevat, zoals verwacht.

Schermafbeelding van geopende geheugeninspecteur met een geïnspecteerde int32-array. Alle array-elementen zijn gemarkeerd.

Vervolgens onthullen ze de lastNumber variabele uit het Scope -paneel en merken ze dat de aanwijzer naar een geheel getal buiten de array wijst! Uitgerust met deze kennis realiseert de programmeur zich dat ze de pointer-offset op regel 8 verkeerd hebben geteld. Het had ptr + arraySize - 1 moeten zijn.

Schermafbeelding van geopende geheugeninspecteur met gemarkeerd geheugen waarnaar wordt verwezen door een aanwijzer met de naam 'lastNumber'. Het gemarkeerde geheugen ligt direct na de laatste byte van de eerder gemarkeerde array.

Hoewel dit een speelgoedvoorbeeld is, illustreert het hoe objectaccentuering effectief de grootte en positie van geheugenobjecten overbrengt, waardoor u beter kunt begrijpen wat er in het geheugen van uw C/C++-app gebeurt.

Hoe DevTools uitzoekt wat moet worden benadrukt

In deze sectie bekijken we het ecosysteem van tools die foutopsporing in C/C++ mogelijk maken. In het bijzonder leert u hoe DevTools, V8, de C/C++ DWARF-extensie en Emscripten C/C++-foutopsporing in Chrome mogelijk maken.

Om de volledige kracht van C/C++-foutopsporing in DevTools te benutten, hebt u twee dingen nodig:

  • De C/C++ DWARF-extensie geïnstalleerd in Chrome
  • C/C++-bronbestanden gecompileerd naar WebAssembly met de nieuwste Emscripten-compiler, zoals aangegeven in deze blogpost

Maar waarom? V8 , de JavaScript- en WebAssembly-engine van Chrome, weet niet hoe C of C++ moet worden uitgevoerd. Dankzij Emscripten , een C/C++ naar WebAssembly-compiler, kunt u apps die in C of C++ zijn gebouwd, compileren als WebAssembly en deze in de browser uitvoeren!

Tijdens het compileren zal emscripten DWARF-foutopsporingsgegevens in uw binaire bestand insluiten. Op een hoog niveau helpen deze gegevens de extensie om erachter te komen welke WebAssembly-variabelen overeenkomen met uw C/C++-variabelen, en meer. Op deze manier kan DevTools u uw C++-variabelen laten zien, ondanks dat V8 daadwerkelijk WebAssembly draait. Als je nieuwsgierig bent, bekijk dan deze blogpost voor een voorbeeld van DWARF-foutopsporingsgegevens.

Dus wat gebeurt er eigenlijk als je het lastNumber onthult? Zodra u op het geheugenpictogram klikt, controleert DevTools welke variabele u wilt inspecteren. Vervolgens wordt de extensie opgevraagd over het gegevenstype en de locatie van lastNumber . Zodra de extensie met die informatie reageert, kan de Memory Inspector het relevante stukje geheugen weergeven en het type kennen, en ook de grootte van het object.

Als je in het eerdere voorbeeld naar lastNumber kijkt, merk je misschien dat we lastNumber: int * hebben geïnspecteerd, maar de chip in de Memory Inspector zegt *lastNumber: int , wat geeft dat? De inspecteur gebruikt pointer-dereferentie in C++-stijl om het type object aan te geven dat aan u wordt getoond! Als u een aanwijzer inspecteert, zal de inspecteur u laten zien waarnaar deze verwijst.

Aanhoudende hoogtepunten van debugger-stappen

Wanneer u een object in de Memory Inspector onthult en met de debugger stapt, blijft de Inspector de markering behouden als hij denkt dat deze nog steeds van toepassing is. In eerste instantie hadden we deze functie niet op onze routekaart staan, maar we realiseerden ons al snel dat dit uw foutopsporingservaring in gevaar brengt. Stel je voor dat je de array na elke stap opnieuw moet inspecteren, zoals in de onderstaande video!

Wanneer de debugger een nieuw breekpunt tegenkomt, vraagt ​​de Memory Inspector opnieuw naar V8 en de extensie voor de variabele die aan de vorige highlight is gekoppeld. Vervolgens vergelijkt het de locaties en typen van de objecten. Als ze overeenkomen, blijft het hoogtepunt bestaan. In de video hierboven is er een for-loop die naar de array x schrijft. Deze bewerkingen veranderen het type of de positie van de array niet, dus deze blijft gemarkeerd.

Je vraagt ​​je misschien af ​​welke invloed dit heeft op de pointers. Als u een gemarkeerde aanwijzer hebt en deze opnieuw aan een ander object toewijst, verschillen de oude en nieuwe posities van de gemarkeerde objecten en verdwijnt de markering. Omdat het nieuw aangewezen object overal in het WebAssembly-geheugen kan voorkomen en waarschijnlijk weinig relatie zal hebben met de vorige geheugenlocatie, is het verwijderen van de markering duidelijker dan naar een nieuwe geheugenlocatie springen. U kunt de aanwijzer opnieuw markeren door op het geheugenpictogram in het bereikvenster te klikken.

Conclusie

In dit artikel worden onze verbeteringen aan de Memory Inspector voor foutopsporing in C/C++ beschreven. We hopen dat de nieuwe functies het debuggen van het geheugen van uw C/C++-apps zullen vereenvoudigen! Als je suggesties hebt om het verder te verbeteren, laat het ons dan weten door een bug in te dienen !

Wat is het volgende

Voor meer informatie, zie: