Aangepaste weergaven van C++-objecten maken in het foutopsporingsprogramma met behulp van het Natvis-framework
Het Visual Studio Natvis-framework past de manier aan waarop systeemeigen typen worden weergegeven in vensters voor foutopsporingsprogrammavariabelen, zoals de Locals en Watch-vensters, en in DataTips. Natvis-visualisaties kunnen helpen de typen die u maakt beter zichtbaar te maken tijdens foutopsporing.
Natvis vervangt het autoexp.dat-bestand in eerdere versies van Visual Studio door XML-syntaxis, betere diagnose, versiebeheer en ondersteuning voor meerdere bestanden.
Notitie
Natvis-aanpassingen werken met klassen en structs, maar niet met typedefs.
Natvis-visualisaties
U gebruikt het Natvis-framework om visualisatieregels te maken voor de typen die u maakt, zodat ontwikkelaars deze gemakkelijker kunnen zien tijdens foutopsporing.
In de volgende afbeelding ziet u bijvoorbeeld een variabele van het type Windows::UI::XAML::Controls::TextBox in een foutopsporingsprogrammavenster zonder dat aangepaste visualisaties zijn toegepast.
In de gemarkeerde rij wordt de eigenschap Text
van de klasse TextBox
weergegeven. De complexe klassehiërarchie maakt het moeilijk om deze eigenschap te vinden. Het foutopsporingsprogramma weet niet hoe u het aangepaste tekenreekstype interpreteert, zodat u de tekenreeks niet in het tekstvak kunt zien.
Dezelfde TextBox
ziet er veel eenvoudiger uit in het variabelevenster wanneer aangepaste visualisatieregels van Natvis worden toegepast. De belangrijke leden van de klasse worden samen weergegeven en het foutopsporingsprogramma toont de onderliggende tekenreekswaarde van het aangepaste tekenreekstype.
.natvis-bestanden gebruiken in C++-projecten
Natvis maakt gebruik van .natvis bestanden om visualisatieregels op te geven. Een .natvis--bestand is een XML-bestand met een .natvis--extensie. Het Natvis-schema wordt gedefinieerd in <VS-installatiemap>\Xml\Schemas\1033\natvis.xsd.
De basisstructuur van een bestand .natvis is een of meer Type
elementen die visualisatievermeldingen vertegenwoordigen. De volledig gekwalificeerde naam van elk Type
element wordt opgegeven in het kenmerk Name
.
<?xml version="1.0" encoding="utf-8"?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
<Type Name="MyNamespace::CFoo">
.
.
</Type>
<Type Name="...">
.
.
</Type>
</AutoVisualizer>
Visual Studio biedt enkele .natvis--bestanden in de map <VS-installatiemap>\Common7\Packages\Debugger\Visualizers map. Deze bestanden hebben visualisatieregels voor veel algemene typen en kunnen fungeren als voorbeelden voor het schrijven van visualisaties voor nieuwe typen.
Een NATVIS-bestand toevoegen aan een C++-project
U kunt een .natvis--bestand toevoegen aan een C++-project.
Voeg een nieuw .natvis- bestand toe:
Selecteer het C++-projectknooppunt in Solution Explorer-en selecteer Project>Nieuw item toevoegen, of klik met de rechtermuisknop op het project en selecteer Toevoegen>Nieuw item.
Als u niet alle itemsjablonen ziet, kiest u Alle sjablonen weergeven.
Selecteer in het dialoogvenster Add New ItemVisual C++>Utility>Het visualisatiebestand voor foutopsporingsprogramma (.natvis).
Geef het bestand een naam en selecteer Toevoegen.
Het nieuwe bestand wordt toegevoegd aan Solution Explorer-en wordt geopend in het documentvenster van Visual Studio.
Het foutopsporingsprogramma van Visual Studio laadt automatisch .natvis--bestanden in C++-projecten en bevat deze standaard ook in het .pdb--bestand wanneer het project wordt gebouwd. Als u fouten in de ingebouwde app opslaadt, laadt het foutopsporingsprogramma het .natvis--bestand uit het .pdb--bestand, zelfs als u het project niet hebt geopend. Als u het bestand .natvis niet wilt opnemen in de .pdb-, kunt u het uitsluiten van het ingebouwde .pdb--bestand.
Een .natvis--bestand uitsluiten van een .pdb-:
Selecteer het .natvis--bestand in Solution Exploreren selecteer het pictogram Eigenschappen of klik met de rechtermuisknop op het bestand en selecteer Eigenschappen.
Gebruik de vervolgkeuzelijst, klik op de pijl naast Uitgesloten van build en selecteer Ja, en selecteer vervolgens OK.
Notitie
Voor het opsporen van fouten in uitvoerbare projecten gebruikt u de oplossingsitems om alle .natvis--bestanden toe te voegen die zich niet in de .pdb-bevinden, omdat er geen C++-project beschikbaar is.
Notitie
Natvis-regels die zijn geladen vanuit een .pdb- zijn alleen van toepassing op de typen in de modules waarnaar de .pdb- verwijst. Als Module1.pdb- bijvoorbeeld een Natvis-vermelding heeft voor een type met de naam Test
, is dit alleen van toepassing op de klasse Test
in Module1.dll. Als een andere module ook een klasse met de naam Test
definieert, is de Module1.pdb- Natvis-vermelding niet van toepassing.
Een .natvis--bestand installeren en registreren via een VSIX-pakket:
Een VSIX-pakket kan .natvis--bestanden installeren en registreren. Ongeacht waar ze zijn geïnstalleerd, worden alle geregistreerde .natvis--bestanden automatisch opgehaald tijdens foutopsporing.
Neem het .natvis--bestand op in het VSIX-pakket. Bijvoorbeeld voor het volgende projectbestand:
<?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="14.0"> <ItemGroup> <VSIXSourceItem Include="Visualizer.natvis" /> </ItemGroup> </Project>
Registreer het bestand .natvis in het bestand source.extension.vsixmanifest:
<?xml version="1.0" encoding="utf-8"?> <PackageManifest Version="2.0.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2011" xmlns:d="http://schemas.microsoft.com/developer/vsx-schema-design/2011"> <Assets> <Asset Type="NativeVisualizer" Path="Visualizer.natvis" /> </Assets> </PackageManifest>
Natvis-bestandslocaties
U kunt .natvis--bestanden toevoegen aan uw gebruikersmap of aan een systeemmap, als u wilt dat ze van toepassing zijn op meerdere projecten.
De .natvis--bestanden worden in de volgende volgorde geëvalueerd:
Alle .natvis--bestanden die zijn ingesloten in een .pdb- terwijl u aan het debuggen bent, tenzij er een bestand met dezelfde naam bestaat in het geladen project.
Alle .natvis- bestanden die zich in een geladen C++-project of een oplossing op het hoogste niveau bevinden. Deze groep bevat alle geladen C++-projecten, waaronder klassebibliotheken, maar geen projecten in andere talen.
Alle .natvis--bestanden die zijn geïnstalleerd en geregistreerd via een VSIX-pakket.
- De gebruikersspecifieke Natvis-map (bijvoorbeeld %USERPROFILE%\Documents\Visual Studio 2022\Visualizers).
- De gebruikersspecifieke Natvis-map (bijvoorbeeld %USERPROFILE%\Documents\Visual Studio 2019\Visualizers).
- De natvis-map voor het hele systeem (<Microsoft Visual Studio-installatiemap>\Common7\Packages\Debugger\Visualizers). Deze map bevat de .natvis--bestanden die zijn geïnstalleerd met Visual Studio. Als u beheerdersmachtigingen hebt, kunt u bestanden toevoegen aan deze map.
.natvis-bestanden wijzigen tijdens foutopsporing
U kunt een .natvis--bestand wijzigen in de IDE tijdens het opsporen van fouten in het project. Open het bestand in hetzelfde exemplaar van Visual Studio waarmee u fouten opspoort, wijzig het en sla het op. Zodra het bestand is opgeslagen, worden de Watch- en Locals-vensters bijgewerkt om de wijziging weer te geven.
U kunt ook .natvis--bestanden toevoegen of verwijderen in een oplossing die u aan het debuggen bent, en Visual Studio voegt de relevante visualisaties toe of verwijdert ze.
U kunt .natvis--bestanden die zijn ingesloten in .pdb bestanden niet bijwerken terwijl u foutopsporing uitvoert.
Als u het bestand .natvis buiten Visual Studio wijzigt, worden de wijzigingen niet automatisch doorgevoerd. Als u de foutopsporingsprogrammavensters wilt bijwerken, kunt u de opdracht .natvisreload opnieuw uitvoeren in het venster Direct. Vervolgens worden de wijzigingen van kracht zonder de foutopsporingssessie opnieuw op te starten.
Gebruik ook de opdracht .natvisreload om het .natvis--bestand bij te werken naar een nieuwere versie. Het bestand .natvis kan bijvoorbeeld worden ingecheckt bij broncodebeheer en u wilt recente wijzigingen ophalen die iemand anders heeft aangebracht.
Expressies en opmaak
Natvis-visualisaties maken gebruik van C++-expressies om de gegevensitems op te geven die moeten worden weergegeven. Naast de verbeteringen en beperkingen van C++-expressies in het foutopsporingsprogramma, die worden beschreven in Contextoperator (C++), moet u rekening houden met het volgende:
Natvis-expressies worden geëvalueerd in de context van het object dat wordt gevisualiseerd, niet het huidige stackframe.
x
in een Natvis-expressie verwijst bijvoorbeeld naar het veld met de naam x in het object dat wordt gevisualiseerd, niet naar een lokale variabele met de naam x in de huidige functie. U hebt geen toegang tot lokale variabelen in Natvis-expressies, hoewel u toegang hebt tot globale variabelen.Natvis-expressies staan functie-evaluatie of bijwerkingen niet toe. Functie-aanroepen en toewijzingsoperatoren worden genegeerd. Omdat intrinsieke functies van het foutopsporingsprogramma neveneffectvrij zijn, kunnen ze vrij worden aangeroepen vanuit een Natvis-expressie, ook al zijn andere functieaanroepen niet toegestaan.
Als u wilt bepalen hoe een expressie wordt weergegeven, kunt u een van de notatieaanduidingen gebruiken die worden beschreven in Opmaakaanduidingen in C++. Opmaakparameters worden genegeerd wanneer een element intern door Natvis wordt gebruikt, zoals de
Size
-expressie in een ArrayItems-uitbreiding.
Notitie
Omdat het Natvis-document XML is, kunnen uw expressies niet rechtstreeks gebruikmaken van het en-teken, groter dan, kleiner dan of shift-operatoren. U moet deze tekens in zowel de hoofdtekst van het item als de voorwaardeinstructies escapen. Bijvoorbeeld:
\<Item Name="HiByte"\>(byte)(_flags \>\> 24),x\</Item\>
\<Item Name="HiByteStatus" Condition="(_flags \& 0xFF000000) == 0"\>"None"\</Item\>
\<Item Name="HiByteStatus" Condition="(_flags \& 0xFF000000) != 0"\>"Some"\</Item\>
Natvis-weergaven
U kunt verschillende Natvis-weergaven definiëren om typen op verschillende manieren weer te geven. Hier ziet u bijvoorbeeld een visualisatie van std::vector
waarmee een vereenvoudigde weergave met de naam simple
wordt gedefinieerd. De DisplayString
en de ArrayItems
-elementen worden weergegeven in de standaardweergave en de simple
weergave, terwijl de [size]
en [capacity]
items niet worden weergegeven in de simple
weergave.
<Type Name="std::vector<*>">
<DisplayString>{{ size={_Mylast - _Myfirst} }}</DisplayString>
<Expand>
<Item Name="[size]" ExcludeView="simple">_Mylast - _Myfirst</Item>
<Item Name="[capacity]" ExcludeView="simple">_Myend - _Myfirst</Item>
<ArrayItems>
<Size>_Mylast - _Myfirst</Size>
<ValuePointer>_Myfirst</ValuePointer>
</ArrayItems>
</Expand>
</Type>
Gebruik in het venster Watch de opmaakspecificator ,view om een alternatieve weergave op te geven. De eenvoudige weergave wordt weergegeven als vec, view(simple):
Natvis-fouten
Wanneer het foutopsporingsprogramma fouten in een visualisatievermelding tegenkomt, worden deze genegeerd. Het type wordt in de onbewerkte vorm weergegeven of er wordt een andere geschikte visualisatie gekozen. U kunt natvis-diagnostische gegevens gebruiken om te begrijpen waarom het foutopsporingsprogramma een visualisatievermelding heeft genegeerd en om onderliggende syntaxis en parseringsfouten te bekijken.
Diagnostische gegevens van Natvis inschakelen:
- Onder Hulpmiddelen>opties (of Foutopsporing>opties) >Foutopsporing>uitvoervenster, stelt u Natvis diagnostische berichten (alleen C++) in op Fout, Waarschuwingof Uitgebreideen selecteer vervolgens OK.
De fouten worden weergegeven in het venster Uitvoer.
Natvis-syntaxisreferentie
De volgende elementen en kenmerken kunnen worden gebruikt in het Natvis-bestand.
AutoVisualizer-element
Het element AutoVisualizer
is het hoofdknooppunt van het .natvis-bestand en bevat de naamruimte xmlns:
kenmerk.
<?xml version="1.0" encoding="utf-8"?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
.
.
</AutoVisualizer>
Het element AutoVisualizer
kan Type, HResult, UIVisualizeren CustomVisualizer onderliggende elementen hebben.
Type element
Een eenvoudige Type
ziet er als volgt uit:
<Type Name="[fully qualified type name]">
<DisplayString Condition="[Boolean expression]">[Display value]</DisplayString>
<Expand>
...
</Expand>
</Type>
Het element Type
geeft het volgende op:
Voor welk type de visualisatie moet worden gebruikt (het kenmerk
Name
).Hoe de waarde van een object van dat type eruit moet zien (het
DisplayString
element).Hoe de leden van het type eruit moeten zien wanneer de gebruiker het type in een variabelevenster uitvouwt (het knooppunt
Expand
).
Sjabloonklassen
Het kenmerk Name
van het Type
element accepteert een sterretje *
als jokerteken dat kan worden gebruikt voor sjabloonklassenamen.
In het volgende voorbeeld wordt dezelfde visualisatie gebruikt of het object een CAtlArray<int>
of een CAtlArray<float>
is. Als er een specifieke visualisatievermelding is voor een CAtlArray<float>
, heeft deze voorrang op de algemene vermelding.
<Type Name="ATL::CAtlArray<*>">
<DisplayString>{{Count = {m_nSize}}}</DisplayString>
</Type>
U kunt verwijzen naar sjabloonparameters in de visualisatievermelding met behulp van macro's $T 1, $T 2 enzovoort. Zie de .natvis- bestanden die zijn verzonden met Visual Studio voor voorbeelden van deze macro's.
Type overeenkomende visualisatie
Als een visualisatievermelding niet kan worden gevalideerd, wordt de volgende beschikbare visualisatie gebruikt.
Overgenomen kenmerk
Het optionele kenmerk Inheritable
geeft aan of een visualisatie alleen van toepassing is op een basistype of op een basistype en alle afgeleide typen. De standaardwaarde van Inheritable
is true
.
In het volgende voorbeeld is de visualisatie alleen van toepassing op het BaseClass
type:
<Type Name="Namespace::BaseClass" Inheritable="false">
<DisplayString>{{Count = {m_nSize}}}</DisplayString>
</Type>
Prioriteitskenmerk
Het optionele kenmerk Priority
geeft de volgorde aan waarin alternatieve definities moeten worden gebruikt, als een definitie niet kan worden geparseerd. De mogelijke waarden van Priority
zijn: Low
, MediumLow
,Medium
, MediumHigh
en High
. De standaardwaarde is Medium
. Het kenmerk Priority
onderscheidt zich alleen van prioriteiten binnen hetzelfde .natvis--bestand.
In het volgende voorbeeld wordt eerst de vermelding geparseerd die overeenkomt met de STL van 2015. Als dit niet kan worden geparseerd, wordt de alternatieve vermelding gebruikt voor de 2013-versie van de STL:
<!-- VC 2013 -->
<Type Name="std::reference_wrapper<*>" Priority="MediumLow">
<DisplayString>{_Callee}</DisplayString>
<Expand>
<ExpandedItem>_Callee</ExpandedItem>
</Expand>
</Type>
<!-- VC 2015 -->
<Type Name="std::reference_wrapper<*>">
<DisplayString>{*_Ptr}</DisplayString>
<Expand>
<Item Name="[ptr]">_Ptr</Item>
</Expand>
</Type>
Optioneel kenmerk
U kunt een Optional
kenmerk op elk knooppunt plaatsen. Als een subexpressie in een optioneel knooppunt niet kan worden geparseerd, negeert het foutopsporingsprogramma dat knooppunt, maar past de rest van de Type
regels toe. In het volgende type is [State]
niet optioneel, maar [Exception]
is optioneel. Als MyNamespace::MyClass
een veld heeft met de naam _M_exceptionHolder
, worden zowel het [State]
-knooppunt als het [Exception]
-knooppunt weergegeven, maar als er geen _M_exceptionHolder
veld is, wordt alleen het [State]
knooppunt weergegeven.
<Type Name="MyNamespace::MyClass">
<Expand>
<Item Name="[State]">_M_State</Item>
<Item Name="[Exception]" Optional="true">_M_exceptionHolder</Item>
</Expand>
</Type>
Voorwaardekenmerk
Het optionele kenmerk Condition
is beschikbaar voor veel visualisatie-elementen en geeft aan wanneer een visualisatieregel moet worden gebruikt. Als de expressie in het voorwaardekenmerk wordt omgezet in false
, is de visualisatieregel niet van toepassing. Als het resulteert in true
of als er geen Condition
kenmerk is, is de visualisatie van toepassing. U kunt dit kenmerk gebruiken voor if-else-logica in de visualisatievermeldingen.
De volgende visualisatie bevat bijvoorbeeld twee DisplayString
elementen voor een slim aanwijzertype. Wanneer het _Myptr
lid leeg is, wordt de voorwaarde van het eerste DisplayString
-element omgezet in true
, zodat het formulier wordt weergegeven. Wanneer het _Myptr
lid niet leeg is, resulteert de voorwaarde in false
en wordt het tweede DisplayString
element weergegeven.
<Type Name="std::auto_ptr<*>">
<DisplayString Condition="_Myptr == 0">empty</DisplayString>
<DisplayString>auto_ptr {*_Myptr}</DisplayString>
<Expand>
<ExpandedItem>_Myptr</ExpandedItem>
</Expand>
</Type>
IncludeView- en ExcludeView-kenmerken
De kenmerken IncludeView
en ExcludeView
geven elementen op die in bepaalde weergaven moeten worden weergegeven of niet. In de volgende Natvis-specificatie van std::vector
worden in de simple
weergave bijvoorbeeld niet de [size]
- en [capacity]
items weergegeven.
<Type Name="std::vector<*>">
<DisplayString>{{ size={_Mylast - _Myfirst} }}</DisplayString>
<Expand>
<Item Name="[size]" ExcludeView="simple">_Mylast - _Myfirst</Item>
<Item Name="[capacity]" ExcludeView="simple">_Myend - _Myfirst</Item>
<ArrayItems>
<Size>_Mylast - _Myfirst</Size>
<ValuePointer>_Myfirst</ValuePointer>
</ArrayItems>
</Expand>
</Type>
U kunt de kenmerken IncludeView
en ExcludeView
voor typen en voor afzonderlijke leden gebruiken.
Versie-element
Met het Version
-element wordt een visualisatie-item beperkt tot een specifieke module en versie. Het element Version
helpt bij het voorkomen van naamconflicten, vermindert onbedoelde verschillen en maakt verschillende visualisaties voor verschillende typeversies mogelijk.
Als een algemeen headerbestand dat wordt gebruikt door verschillende modules een type definieert, wordt de versievisualisatie alleen weergegeven wanneer het type zich in de opgegeven moduleversie bevindt.
In het volgende voorbeeld is de visualisatie alleen van toepassing op het DirectUI::Border
type dat in de Windows.UI.Xaml.dll
van versie 1.0 tot en met 1.5 is gevonden.
<Type Name="DirectUI::Border">
<Version Name="Windows.UI.Xaml.dll" Min="1.0" Max="1.5"/>
<DisplayString>{{Name = {*(m_pDO->m_pstrName)}}}</DisplayString>
<Expand>
<ExpandedItem>*(CBorder*)(m_pDO)</ExpandedItem>
</Expand>
</Type>
U hebt niet zowel Min
als Max
nodig. Dit zijn optionele kenmerken. Er worden geen jokertekens ondersteund.
Het kenmerk Name
heeft de indeling bestandsnaam.ext-, zoals hello.exe of some.dll. Er zijn geen padnamen toegestaan.
DisplayString-element
Het element DisplayString
geeft een tekenreeks op die moet worden weergegeven als de waarde van een variabele. Het accepteert willekeurige tekenreeksen die zijn gemengd met expressies. Alles binnen accolades wordt geïnterpreteerd als een expressie. Bijvoorbeeld de volgende DisplayString
vermelding:
<Type Name="CPoint">
<DisplayString>{{x={x} y={y}}}</DisplayString>
</Type>
Betekent dat variabelen van het type CPoint
worden weergegeven zoals in deze afbeelding:
In de expressie DisplayString
bevinden x
en y
, die lid zijn van CPoint
, zich binnen accolades, waardoor hun waarden worden geëvalueerd. In het voorbeeld ziet u ook hoe u kunt ontsnappen aan een accolade door gebruik te maken van dubbele accolades ({{
of }}
).
Notitie
Het DisplayString
-element is het enige element dat willekeurige tekenreeksen en accoladesyntaxis accepteert. Alle andere visualisatie-elementen accepteren alleen expressies die het foutopsporingsprogramma kan evalueren.
Het element StringView
Het element StringView
definieert een waarde die het foutopsporingsprogramma naar de ingebouwde tekstvisualr kan verzenden. Bijvoorbeeld, op basis van de volgende visualisatie voor het ATL::CStringT
type:
<Type Name="ATL::CStringT<wchar_t,*>">
<DisplayString>{m_pszData,su}</DisplayString>
</Type>
Het CStringT
-object wordt weergegeven in een variabelevenster zoals in dit voorbeeld:
Als u een StringView
-element toevoegt, wordt aan het foutopsporingsprogramma aangegeven dat de waarde kan worden weergegeven als tekstvisualisatie.
<Type Name="ATL::CStringT<wchar_t,*>">
<DisplayString>{m_pszData,su}</DisplayString>
<StringView>m_pszData,su</StringView>
</Type>
Tijdens foutopsporing kunt u het vergrootglaspictogram naast de variabele selecteren en vervolgens Text Visualizer selecteren om de tekenreeks weer te geven waarnaar m_pszData verwijst.
De expressie {m_pszData,su}
bevat een C++-indelingsaanduiding suom de waarde weer te geven als een Unicode-tekenreeks. Zie Opmaakaanduidingen in C++voor meer informatie.
Element uitvouwen
Met het optionele Expand
-knooppunt worden de onderliggende elementen van een gevisualiseerd type aangepast wanneer u het type in een variabelevenster uitvouwt. Het Expand
knooppunt accepteert een lijst met onderliggende knooppunten die de onderliggende elementen definiëren.
Als een
Expand
knooppunt niet is gespecificeerd in een visualisatievermelding, gebruiken de kinderen de standaarduitbreidingsregels.Als een
Expand
knooppunt is opgegeven zonder onderliggende knooppunten, kan het type niet worden uitgebreid in de debugvensters.
Uibreiding van artikel
Het element Item
is het meest eenvoudige en algemene element in een Expand
-knooppunt.
Item
definieert een enkelvoudig kindelement. Een CRect
-klasse met velden top
, left
, right
en bottom
heeft bijvoorbeeld de volgende visualisatievermelding:
<Type Name="CRect">
<DisplayString>{{top={top} bottom={bottom} left={left} right={right}}}</DisplayString>
<Expand>
<Item Name="Width">right - left</Item>
<Item Name="Height">bottom - top</Item>
</Expand>
</Type>
In het venster foutopsporingsprogramma ziet het CRect
type eruit als in dit voorbeeld:
Het foutopsporingsprogramma evalueert de expressies die zijn opgegeven in de elementen Width
en Height
en toont de waarden in de kolom Waarde van het variabelevenster.
Het foutopsporingsprogramma maakt voor elke aangepaste expansie automatisch het knooppunt [Onbewerkte weergave] aan. In de voorgaande schermopname ziet u de [Onbewerkte weergave] knooppunt uitgevouwen om te laten zien hoe de standaard onbewerkte weergave van het object verschilt van de Natvis-visualisatie. De standaarduitbreiding maakt een subboom voor de basisklasse en vermeldt alle gegevensleden van de basisklasse als kinderen.
Notitie
Als de expressie van het itemelement verwijst naar een complex type, is het item knooppunt zelf uitbreidbaar.
Uitbreiding van ArrayItems
Gebruik het ArrayItems
-knooppunt om het type te laten interpreteren als een matrix en de afzonderlijke elementen ervan weer te geven met het Visual Studio-foutopsporingsprogramma. De visualisatie voor std::vector
is een goed voorbeeld:
<Type Name="std::vector<*>">
<DisplayString>{{size = {_Mylast - _Myfirst}}}</DisplayString>
<Expand>
<Item Name="[size]">_Mylast - _Myfirst</Item>
<Item Name="[capacity]">(_Myend - _Myfirst)</Item>
<ArrayItems>
<Size>_Mylast - _Myfirst</Size>
<ValuePointer>_Myfirst</ValuePointer>
</ArrayItems>
</Expand>
</Type>
Een std::vector
toont de afzonderlijke elementen wanneer deze in het variabelevenster worden uitgevouwen:
Het knooppunt ArrayItems
moet het volgende hebben:
- Een
Size
-expressie (die moet resulteren in een geheel getal) voor het foutopsporingsprogramma om de lengte van de matrix te begrijpen. - Een
ValuePointer
-expressie die verwijst naar het eerste element (dat een aanwijzer moet zijn van een elementtype dat nietvoid*
is).
De standaardwaarde van de ondergrens van de matrix is 0. Als u de waarde wilt overschrijven, gebruikt u een LowerBound
element. De .natvis bestanden die zijn verzonden met Visual Studio, hebben voorbeelden.
Notitie
U kunt de []
-operator gebruiken, bijvoorbeeld vector[i]
, met een enkeledimensionale matrixvisualisatie die gebruikmaakt van ArrayItems
, zelfs als het type zelf (bijvoorbeeld CATLArray
) deze operator niet toestaat.
U kunt ook multidimensionale matrices opgeven. In dat geval heeft het foutopsporingsprogramma iets meer informatie nodig om onderliggende elementen correct weer te geven:
<Type Name="Concurrency::array<*,*>">
<DisplayString>extent = {_M_extent}</DisplayString>
<Expand>
<Item Name="extent">_M_extent</Item>
<ArrayItems Condition="_M_buffer_descriptor._M_data_ptr != 0">
<Direction>Forward</Direction>
<Rank>$T2</Rank>
<Size>_M_extent._M_base[$i]</Size>
<ValuePointer>($T1*) _M_buffer_descriptor._M_data_ptr</ValuePointer>
<LowerBound>0</LowerBound>
</ArrayItems>
</Expand>
</Type>
-
Direction
geeft aan of de matrix zich in volgorde van rij-primaire of kolom-primaire bevindt. -
Rank
geeft de rang van de matrix aan. - Het element
Size
accepteert de impliciete$i
parameter, die wordt vervangen door de dimensieindex om de lengte van de matrix in die dimensie te vinden.- In het vorige voorbeeld moet de expressie
_M_extent.M_base[0]
de lengte van de 0e dimensie geven,_M_extent._M_base[1]
de eerste, enzovoort.
- In het vorige voorbeeld moet de expressie
- De
LowerBound
geeft de ondergrens aan van elke dimensie van de matrix. Voor multidimensionale matrices kunt u een expressie opgeven die gebruikmaakt van de impliciete$i
parameter. De parameter$i
wordt vervangen door de dimensieindex om de ondergrens van de matrix in die dimensie te vinden.- In het vorige voorbeeld beginnen alle dimensies bij 0. Als u echter
($i == 1) ? 1000 : 100
als ondergrens hebt, begint de 0e dimensie bij 100 en begint de eerste dimensie bij 1000.- , zoals
[100, 1000], [100, 1001], [100, 1002], ... [101, 1000], [101, 1001],...
- , zoals
- In het vorige voorbeeld beginnen alle dimensies bij 0. Als u echter
Hier ziet u hoe een tweedimensionaal Concurrency::array
-object eruitziet in het venster foutopsporingsprogramma:
IndexListItems-uitbreiding
U kunt ArrayItems
uitbreiding alleen gebruiken als de matrixelementen aaneengesloten in het geheugen zijn ingedeeld. Het foutopsporingsprogramma gaat naar het volgende element door simpelweg de aanwijzer te verhogen. Als u de index naar het waardeknooppunt wilt bewerken, gebruikt u IndexListItems
knooppunten. Hier volgt een visualisatie met een IndexListItems
knooppunt:
<Type Name="Concurrency::multi_link_registry<*>">
<DisplayString>{{size = {_M_vector._M_index}}}</DisplayString>
<Expand>
<Item Name="[size]">_M_vector._M_index</Item>
<IndexListItems>
<Size>_M_vector._M_index</Size>
<ValueNode>*(_M_vector._M_array[$i])</ValueNode>
</IndexListItems>
</Expand>
</Type>
Het enige verschil tussen ArrayItems
en IndexListItems
is de ValueNode
, die de volledige expressie verwacht voor het ith-element met de impliciete parameter voor $i
.
Notitie
U kunt de []
-operator gebruiken, bijvoorbeeld vector[i]
, met een enkeledimensionale matrixvisualisatie die gebruikmaakt van IndexListItems
, zelfs als het type zelf (bijvoorbeeld CATLArray
) deze operator niet toestaat.
Uitbreiding van LinkedListItems
Als het gevisualiseerde type een gekoppelde lijst vertegenwoordigt, kan de debugger zijn kinderen weergeven met behulp van een LinkedListItems
-knooppunt. De volgende visualisatie voor het type CAtlList
maakt gebruik van LinkedListItems
:
<Type Name="ATL::CAtlList<*,*>">
<DisplayString>{{Count = {m_nElements}}}</DisplayString>
<Expand>
<Item Name="Count">m_nElements</Item>
<LinkedListItems>
<Size>m_nElements</Size>
<HeadPointer>m_pHead</HeadPointer>
<NextPointer>m_pNext</NextPointer>
<ValueNode>m_element</ValueNode>
</LinkedListItems>
</Expand>
</Type>
Het element Size
verwijst naar de lengte van de lijst.
HeadPointer
verwijst naar het eerste element, NextPointer
verwijst naar het volgende element en ValueNode
verwijst naar de waarde van het item.
Het foutopsporingsprogramma evalueert de NextPointer
- en ValueNode
-uitdrukkingen in de context van het LinkedListItems
-knooppuntelement, niet het ouderlijsttype. In het voorgaande voorbeeld heeft CAtlList
een CNode
-klasse (in atlcoll.h
) die een knooppunt van de gekoppelde lijst is.
m_pNext
en m_element
zijn velden van die CNode
klasse, niet van de klasse CAtlList
.
ValueNode
kan leeg blijven of this
gebruiken om naar het LinkedListItems
knooppunt zelf te verwijzen.
Uitbreiding van CustomListItems
Met de CustomListItems
-uitbreiding kunt u aangepaste logica schrijven voor het doorlopen van een gegevensstructuur, zoals een hashtabel. Gebruik CustomListItems
om gegevensstructuren te visualiseren die C++-expressies kunnen gebruiken voor alles wat u moet evalueren, maar niet helemaal in de vorm passen voor ArrayItems
, IndexListItems
of LinkedListItems
.
U kunt Exec
gebruiken om code in een CustomListItems
-uitbreiding uit te voeren met behulp van de variabelen en objecten die in de uitbreiding zijn gedefinieerd. U kunt logische operators, rekenkundige operatoren en toewijzingsoperatoren gebruiken met Exec
. U kunt Exec
niet gebruiken om functies te evalueren, met uitzondering van intrinsieke functies van foutopsporingsprogramma ondersteund door de C++-expressie-evaluator.
De volgende visualisatiefunctie voor CAtlMap
is een uitstekend voorbeeld waarin CustomListItems
geschikt is.
<Type Name="ATL::CAtlMap<*,*,*,*>">
<AlternativeType Name="ATL::CMapToInterface<*,*,*>"/>
<AlternativeType Name="ATL::CMapToAutoPtr<*,*,*>"/>
<DisplayString>{{Count = {m_nElements}}}</DisplayString>
<Expand>
<CustomListItems MaxItemsPerView="5000" ExcludeView="Test">
<Variable Name="iBucket" InitialValue="-1" />
<Variable Name="pBucket" InitialValue="m_ppBins == nullptr ? nullptr : *m_ppBins" />
<Variable Name="iBucketIncrement" InitialValue="-1" />
<Size>m_nElements</Size>
<Exec>pBucket = nullptr</Exec>
<Loop>
<If Condition="pBucket == nullptr">
<Exec>iBucket++</Exec>
<Exec>iBucketIncrement = __findnonnull(m_ppBins + iBucket, m_nBins - iBucket)</Exec>
<Break Condition="iBucketIncrement == -1" />
<Exec>iBucket += iBucketIncrement</Exec>
<Exec>pBucket = m_ppBins[iBucket]</Exec>
</If>
<Item>pBucket,na</Item>
<Exec>pBucket = pBucket->m_pNext</Exec>
</Loop>
</CustomListItems>
</Expand>
</Type>
TreeItems-uitbreiding
Als het gevisualiseerde type een boom vertegenwoordigt, kan de debugger de boomstructuur doorlopen en zijn kinderen weergeven met behulp van een TreeItems
knooppunt. Hier volgt de visualisatie voor het std::map
type met behulp van een TreeItems
-knooppunt:
<Type Name="std::map<*>">
<DisplayString>{{size = {_Mysize}}}</DisplayString>
<Expand>
<Item Name="[size]">_Mysize</Item>
<Item Name="[comp]">comp</Item>
<TreeItems>
<Size>_Mysize</Size>
<HeadPointer>_Myhead->_Parent</HeadPointer>
<LeftPointer>_Left</LeftPointer>
<RightPointer>_Right</RightPointer>
<ValueNode Condition="!((bool)_Isnil)">_Myval</ValueNode>
</TreeItems>
</Expand>
</Type>
De syntaxis is vergelijkbaar met het knooppunt LinkedListItems
.
LeftPointer
, RightPointer
en ValueNode
worden geëvalueerd in de context van de boomknooppuntklasse.
ValueNode
kan leeg blijven of this
gebruiken om naar het TreeItems
knooppunt zelf te verwijzen.
UitgebreidItem-uitbreiding
Het ExpandedItem
-element genereert een samengestelde weergave door eigenschappen van basisklassen of gegevensleden weer te geven alsof ze kinderen zijn van het gevisualiseerde type. De debugger evalueert de opgegeven expressie, en voegt de child nodes van het resultaat toe aan de kindlijst van het gevisualiseerde type.
Het type slimme aanwijzer auto_ptr<vector<int>>
wordt bijvoorbeeld meestal weergegeven als:
Als u de waarden van de vector wilt zien, moet u twee niveaus doorlopen in het variabelevenster, en door het _Myptr
-lid navigeren. Door een ExpandedItem
element toe te voegen, kunt u de _Myptr
variabele uit de hiërarchie elimineren en de vectorelementen rechtstreeks bekijken:
<Type Name="std::auto_ptr<*>">
<DisplayString>auto_ptr {*_Myptr}</DisplayString>
<Expand>
<ExpandedItem>_Myptr</ExpandedItem>
</Expand>
</Type>
In het volgende voorbeeld ziet u hoe u eigenschappen van de basisklasse in een afgeleide klasse samenvoegt. Stel dat de CPanel
klasse is afgeleid van CFrameworkElement
. In plaats van de eigenschappen te herhalen die afkomstig zijn van de basisklasse CFrameworkElement
, voegt de visualisatie van het ExpandedItem
knooppunt deze eigenschappen toe aan de onderliggende lijst van de CPanel
-klasse.
<Type Name="CPanel">
<DisplayString>{{Name = {*(m_pstrName)}}}</DisplayString>
<Expand>
<Item Name="IsItemsHost">(bool)m_bItemsHost</Item>
<ExpandedItem>*(CFrameworkElement*)this,nd</ExpandedItem>
</Expand>
</Type>
De opmaakaanduidingen en, waarmee visualisatiematching voor de afgeleide klasse moet worden uitgeschakeld, zijn hier noodzakelijk. Anders zou de uitdrukking *(CFrameworkElement*)this
ervoor zorgen dat de CPanel
-visualisatie opnieuw wordt toegepast, omdat de standaardregels voor visualisatietypetoewijzing deze als de meest geschikte beschouwen. Gebruik de en opmaakaanduiding om de debugger te instrueren om de basisklassevisualisatie te gebruiken, of de standaarduitbreiding te gebruiken wanneer de basisklasse geen visualisatie heeft.
uitbreiding van synthetische items
Hoewel het ExpandedItem
element een platte weergave van gegevens biedt door hiërarchieën te elimineren, doet het Synthetic
knooppunt het tegenovergestelde. Hiermee kunt u een kunstmatig kindelement maken dat geen resultaat is van een uitdrukking. Het kunstmatige element kan zelf kind elementen hebben. In het volgende voorbeeld gebruikt de visualisatie voor het type Concurrency::array
een Synthetic
-knooppunt om een diagnostisch bericht weer te geven aan de gebruiker:
<Type Name="Concurrency::array<*,*>">
<DisplayString>extent = {_M_extent}</DisplayString>
<Expand>
<Item Name="extent" Condition="_M_buffer_descriptor._M_data_ptr == 0">_M_extent</Item>
<ArrayItems Condition="_M_buffer_descriptor._M_data_ptr != 0">
<Rank>$T2</Rank>
<Size>_M_extent._M_base[$i]</Size>
<ValuePointer>($T1*) _M_buffer_descriptor._M_data_ptr</ValuePointer>
</ArrayItems>
<Synthetic Name="Array" Condition="_M_buffer_descriptor._M_data_ptr == 0">
<DisplayString>Array members can be viewed only under the GPU debugger</DisplayString>
</Synthetic>
</Expand>
</Type>
Intrinsieke uitbreiding
Een aangepaste intrinsieke functie die kan worden aangeroepen vanuit een expressie. Een <Intrinsic>
element moet worden vergezeld van een foutopsporingsprogrammaonderdeel dat de functie implementeert via de interface IDkmIntrinsicFunctionEvaluator140. Zie Implementeren van een aangepaste NatVis intrinsieke functievoor meer informatie over het implementeren van een aangepaste intrinsieke functie.
<Type Name="std::vector<*>">
<Intrinsic Name="size" Expression="(size_t)(_Mypair._Myval2._Mylast - _Mypair._Myval2._Myfirst)" />
<Intrinsic Name="capacity" Expression="(size_t)(_Mypair._Myval2._Myend - _Mypair._Myval2._Myfirst)" />
<DisplayString>{{ size={size()} }}</DisplayString>
<Expand>
<Item Name="[capacity]" ExcludeView="simple">capacity()</Item>
<Item Name="[allocator]" ExcludeView="simple">_Mypair</Item>
<ArrayItems>
<Size>size()</Size>
<ValuePointer>_Mypair._Myval2._Myfirst</ValuePointer>
</ArrayItems>
</Expand>
</Type>
HResult-element
Met het element HResult
kunt u de informatie aanpassen die wordt weergegeven voor een HRESULT- in foutopsporingsprogrammavensters. Het element HRValue
moet de 32-bits waarde van de HRESULT- bevatten die moet worden aangepast. Het element HRDescription
bevat de informatie die moet worden weergegeven in het venster foutopsporingsprogramma.
<HResult Name="MY_E_COLLECTION_NOELEMENTS">
<HRValue>0xABC0123</HRValue>
<HRDescription>No elements in the collection.</HRDescription>
</HResult>
UIVisualizer-element
Een UIVisualizer
-element registreert een plug-in voor grafische visualisaties bij het foutopsporingsprogramma. Een grafische visualisatie maakt een dialoogvenster of een andere interface die een variabele of object op een manier weergeeft die consistent is met het gegevenstype. De visualizer-invoegtoepassing moet worden gemaakt als een VSPackage-en moet een service beschikbaar maken die de debugger kan gebruiken. Het bestand .natvis bevat registratiegegevens voor de invoegtoepassing, zoals de naam, de GUID (Globally Unique Identifier) van de weergegeven service en de typen die kunnen worden gevisualiseerd.
Hier volgt een voorbeeld van een UIVisualizer-element:
<?xml version="1.0" encoding="utf-8"?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
<UIVisualizer ServiceId="{5452AFEA-3DF6-46BB-9177-C0B08F318025}"
Id="1" MenuName="Vector Visualizer"/>
<UIVisualizer ServiceId="{5452AFEA-3DF6-46BB-9177-C0B08F318025}"
Id="2" MenuName="List Visualizer"/>
.
.
</AutoVisualizer>
Een
ServiceId
-Id
kenmerkpaar identificeert eenUIVisualizer
. DeServiceId
is de GUID van de service die het visualizer-pakket beschikbaar maakt.Id
is een unieke identificator waarmee visualisatiehulpmiddelen worden onderscheiden als een dienst meer dan één visualisatiehulpmiddel biedt. In het voorgaande voorbeeld biedt dezelfde visualizer-service twee visualizers.Het kenmerk
MenuName
definieert een visualisatienaam die moet worden weergegeven in de vervolgkeuzelijst naast het vergrootglaspictogram in het foutopsporingsprogramma. Bijvoorbeeld:
Elk type dat is gedefinieerd in het bestand .natvis, moet expliciet een lijst weergeven van ui-visualisaties die het kunnen weergeven. De debugger stemt de visualizerverwijzingen in de typevermeldingen af op de geregistreerde visualizers. De volgende typevermelding voor std::vector
verwijst bijvoorbeeld naar de UIVisualizer
in het voorgaande voorbeeld.
<Type Name="std::vector<int,*>">
<UIVisualizer ServiceId="{5452AFEA-3DF6-46BB-9177-C0B08F318025}" Id="1" />
</Type>
U ziet een voorbeeld van een UIVisualizer
in de extensie Image Watch die wordt gebruikt om bitmaps in het geheugen weer te geven.
Het element CustomVisualizer
CustomVisualizer
is een uitbreidbaar punt dat een VSIX-extensie aangeeft die u schrijft om visualisaties in Visual Studio Code te beheren. Zie de Visual Studio SDKvoor meer informatie over het schrijven van VSIX-extensies.
Het is veel meer werk om een aangepaste visualisatie te schrijven dan een XML Natvis-definitie, maar u bent vrij van beperkingen over wat Natvis doet of niet ondersteunt. Aangepaste visualizers hebben toegang tot de volledige set uitbreidbaarheids-API's van de debugger, die het gedebugde proces kunnen doorzoeken en wijzigen of kunnen communiceren met andere onderdelen van Visual Studio.
U kunt de kenmerken Condition
, IncludeView
en ExcludeView
voor CustomVisualizer
elementen gebruiken.
Beperkingen
Natvis-aanpassingen werken met klassen en structs, maar niet met typedefs.
Natvis biedt geen ondersteuning voor visualisaties voor primitieve typen (bijvoorbeeld int
, bool
) of voor aanwijzers naar primitieve typen. In dit scenario kunt u de indelingsaanduiding gebruiken geschikt voor uw use-case. Als u bijvoorbeeld double* mydoublearray
in uw code gebruikt, kunt u een matrixnotatieaanduiding gebruiken in het venster Watch van het foutopsporingsprogramma, zoals de expressie mydoublearray, [100]
, waarin de eerste 100 elementen worden weergegeven.