Vytváření vlastních zobrazení objektů C++ v ladicím programu pomocí architektury Natvis
Architektura Natvis sady Visual Studio přizpůsobí způsob, jakým se nativní typy zobrazují v oknech proměnných ladicího programu, například v oknech Locals a Watch a Data Tipy. Vizualizace Natvis vám můžou pomoct zajistit, aby byly typy, které vytváříte při ladění, viditelné.
Natvis nahrazuje soubor autoexp.dat v dřívějších verzích sady Visual Studio syntaxí XML, lepší diagnostikou, správou verzí a podporou více souborů.
Poznámka:
Vlastní nastavení Natvis pracují s třídami a strukturami, ale ne typedefs.
Vizualizace Natvis
Architekturu Natvis použijete k vytvoření pravidel vizualizace pro typy, které vytvoříte, aby je vývojáři mohli snadněji zobrazit během ladění.
Například následující obrázek znázorňuje proměnnou typu Windows::UI::XAML::Controls::TextBox v okně ladicího programu bez použití vlastních vizualizací.
Zvýrazněný řádek zobrazuje Text
vlastnost TextBox
třídy. Složitá hierarchie tříd znesnadňuje nalezení této vlastnosti. Ladicí program neví, jak interpretovat vlastní typ řetězce, takže nemůžete zobrazit řetězec uložený uvnitř textového pole.
TextBox
Totéž vypadá mnohem jednodušší v okně proměnné při použití vlastních pravidel vizualizéru Natvis. Důležité členy třídy se zobrazí společně a ladicí program zobrazí základní řetězcovou hodnotu vlastního typu řetězce.
Použití souborů .natvis v projektech C++
Natvis používá soubory .natvis k určení pravidel vizualizace. Soubor .natvis je soubor XML s příponou .natvis . Schéma Natvis je definováno ve <složce> Instalace VS\Xml\Schemas\1033\natvis.xsd.
Základní struktura souboru .natvis je jeden nebo více Type
prvků představujících položky vizualizace. Plně kvalifikovaný název každého Type
prvku je zadán v jeho Name
atributu.
<?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 poskytuje některé soubory .natvis ve <složce> Instalace VS\Common7\Packages\Debugger\Visualizers . Tyto soubory mají pravidla vizualizace pro mnoho běžných typů a můžou sloužit jako příklady pro psaní vizualizací pro nové typy.
Přidání souboru .natvis do projektu C++
Do libovolného projektu C++ můžete přidat soubor .natvis .
Přidání nového souboru .natvis :
Vyberte uzel projektu C++ v Průzkumník řešení a vyberte Přidat novou položku projektu>nebo klikněte pravým tlačítkem myši na projekt a vyberte Přidat>novou položku.
Pokud nevidíte všechny šablony položek, zvolte Zobrazit všechny šablony.
V dialogovém okně Přidat novou položku vyberte soubor vizualizace visual C++>Utility>Debugger (.natvis).
Pojmenujte soubor a vyberte Přidat.
Nový soubor se přidá do Průzkumník řešení a otevře se v podokně dokumentů sady Visual Studio.
Ladicí program sady Visual Studio načte soubory .natvis v projektech C++ automaticky a ve výchozím nastavení je také zahrne do souboru .pdb při sestavení projektu. Pokud ladíte sestavenou aplikaci, ladicí program načte soubor .natvis ze souboru .pdb , i když projekt nemáte otevřený. Pokud nechcete , aby byl soubor .natvis zahrnutý v souboru .pdb, můžete ho vyloučit z vytvořeného souboru .pdb .
Vyloučení souboru .natvis z souboru .pdb:
Vyberte soubor .natvis v Průzkumník řešení a vyberte ikonu Vlastnosti nebo klikněte pravým tlačítkem myši na soubor a vyberte Vlastnosti.
Rozevírací seznam se šipkou vedle možnosti Vyloučeno z sestavení a vyberte Ano a pak vyberte OK.
Poznámka:
Pro ladění spustitelných projektů použijte položky řešení k přidání všech souborů .natvis , které nejsou v souboru .pdb, protože není k dispozici žádný projekt C++.
Poznámka:
Pravidla Natvis načtená z souboru .pdb se vztahují pouze na typy v modulech, na které soubor .pdb odkazuje. Pokud má například Module1.pdb položku Natvis pro typ s názvem Test
, vztahuje se pouze na Test
třídu v Module1.dll. Pokud jiný modul také definuje třídu s názvem Test
, položka Natvis Module1.pdb se na ni nevztahuje.
Instalace a registrace souboru .natvis prostřednictvím balíčku VSIX:
Balíček VSIX může instalovat a registrovat soubory .natvis . Bez ohledu na to, kde jsou nainstalované, se během ladění automaticky vyberou všechny registrované soubory .natvis .
Do balíčku VSIX zahrňte soubor .natvis. Například pro následující soubor projektu:
<?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>
Zaregistrujte soubor .natvis v souboru 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>
Umístění souborů Natvis
Soubory .natvis můžete přidat do uživatelského adresáře nebo do systémového adresáře, pokud je chcete použít pro více projektů.
Soubory .natvis se vyhodnocují v následujícím pořadí:
Všechny soubory .natvis vložené do souboru .pdb , který ladíte, pokud v načteném projektu neexistuje soubor se stejným názvem.
Všechny soubory .natvis , které jsou v načteném projektu C++ nebo řešení nejvyšší úrovně. Tato skupina zahrnuje všechny načtené projekty C++, včetně knihoven tříd, ale ne projektů v jiných jazycích.
Všechny soubory .natvis nainstalované a registrované prostřednictvím balíčku VSIX.
- Adresář Natvis specifický pro uživatele (například %USERPROFILE%\Documents\Visual Studio 2022\Visualizers).
- Adresář Natvis specifický pro uživatele (například %USERPROFILE%\Documents\Visual Studio 2019\Visualizers).
- Adresář Natvis pro celý systém (<instalační složka> sady Microsoft Visual Studio\Common7\Packages\Debugger\Visualizers). Tento adresář obsahuje soubory .natvis , které jsou nainstalovány se sadou Visual Studio. Pokud máte oprávnění správce, můžete do tohoto adresáře přidat soubory.
Úprava souborů .natvis při ladění
Při ladění projektu můžete upravit soubor .natvis v integrovaném vývojovém prostředí (IDE). Otevřete soubor ve stejné instanci sady Visual Studio, pomocí které ladíte, upravte ho a uložte. Jakmile se soubor uloží, aktualizace windows Kukátko a Místní hodnoty tak, aby odrážely změnu.
Soubory .natvis můžete také přidat nebo odstranit v řešení, které ladíte, a Visual Studio přidá nebo odebere relevantní vizualizace.
Při ladění nemůžete aktualizovat soubory .natvis , které jsou vložené do souborů .pdb .
Pokud upravíte soubor .natvis mimo Visual Studio, změny se neprojeví automaticky. Chcete-li aktualizovat okna ladicího programu, můžete znovu vyhodnotit příkaz .natvisreload v příkazovém okně. Změny se pak projeví bez restartování relace ladění.
K upgradu souboru .natvisreload na novější verzi použijte také příkaz .natvisload. Například soubor .natvis může být vrácen do správy zdrojového kódu a chcete vyzvednout nedávné změny, které provedl někdo jiný.
Výrazy a formátování
Vizualizace Natvis používají výrazy jazyka C++ k určení datových položek, které se mají zobrazit. Kromě vylepšení a omezení výrazů jazyka C++ v ladicím programu, které jsou popsány v kontextovém operátoru (C++), mějte na paměti následující:
Výrazy Natvis se vyhodnocují v kontextu vizualizovaného objektu, nikoli v aktuálním rámečku zásobníku. Například
x
ve výrazu Natvis odkazuje na pole pojmenované x v vizualizovaném objektu, nikoli na místní proměnnou s názvem x v aktuální funkci. Ve výrazech Natvis nemáte přístup k místním proměnným, i když máte přístup k globálním proměnným.Výrazy Natvis neumožňují vyhodnocení funkce ani vedlejší účinky. Volání funkcí a operátory přiřazení se ignorují. Vzhledem k tomu, že vnitřní funkce ladicího programu jsou bez vedlejšího efektu, mohou být volně volány z jakéhokoli výrazu Natvis, i když jsou jiná volání funkcí zakázána.
Pokud chcete určit, jak se výraz zobrazí, můžete použít libovolný specifikátor formátu popsaný ve specifikátorech formátu v jazyce C++. Specifikátory formátu se ignorují, když se položka interně používá v Natvis, například
Size
výraz v rozšíření ArrayItems.
Poznámka:
Vzhledem k tomu, že dokument Natvis je XML, nemohou výrazy přímo používat ampersand, větší než, menší než nebo operátory shift. Tyto znaky je nutné u řídicích znaků v textu položky i v příkazech podmínky. Příklad:
\<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\>
Zobrazení Natvis
Různá zobrazení Natvis můžete definovat tak, aby zobrazovala typy různými způsoby. Tady je například vizualizace std::vector
, která definuje zjednodušené zobrazení s názvem simple
. Prvky DisplayString
se ArrayItems
zobrazují ve výchozím zobrazení a simple
v zobrazení, zatímco [size]
položky se [capacity]
v simple
zobrazení nezobrazují.
<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>
V okně Kukátko zadejte alternativní zobrazení pomocí specifikátoru formátu zobrazení. Jednoduché zobrazení se zobrazí jako vec,view(simple):
Chyby Natvis
Když ladicí program narazí na chyby v položce vizualizace, ignoruje je. Buď zobrazí typ v nezpracované podobě, nebo vybere jinou vhodnou vizualizaci. Pomocí diagnostiky Natvis můžete zjistit, proč ladicí program ignoroval položku vizualizace, a zobrazit základní syntaxi a analyzovat chyby.
Zapnutí diagnostiky Natvis:
- V části Možnosti nástrojů>(nebo Možnosti ladění>) >Okno výstupu ladění>nastavte diagnostické zprávy Natvis (pouze C++) na hodnotu Chyba, Upozornění nebo Podrobné a pak vyberte OK.
Chyby se zobrazí v okně Výstup .
Odkaz na syntaxi Natvis
Následující prvky a atributy lze použít v souboru Natvis.
Element AutoVisualizer
Element AutoVisualizer
je kořenový uzel souboru .natvis a obsahuje atribut oboru názvů xmlns:
.
<?xml version="1.0" encoding="utf-8"?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
.
.
</AutoVisualizer>
Element AutoVisualizer
může obsahovat podřízené objekty Type, HResult, UIVisualizer a CustomVisualizer .
Element Type
Základní Type
příklad vypadá takto:
<Type Name="[fully qualified type name]">
<DisplayString Condition="[Boolean expression]">[Display value]</DisplayString>
<Expand>
...
</Expand>
</Type>
Prvek Type
určuje:
Jaký typ vizualizace se má použít (
Name
atribut).Jaká hodnota objektu daného typu by měla vypadat (
DisplayString
prvek).Jak by členové typu měli vypadat, když uživatel rozbalí typ v okně proměnné (uzel
Expand
).
Šablonované třídy
Atribut Name
elementu Type
přijímá hvězdičku *
jako zástupný znak, který lze použít pro názvy šablon třídy.
V následujícím příkladu se stejná vizualizace používá bez ohledu na to, zda je objekt nebo CAtlArray<int>
.CAtlArray<float>
Pokud existuje pro konkrétní CAtlArray<float>
položku vizualizace, má přednost před obecnou položkou.
<Type Name="ATL::CAtlArray<*>">
<DisplayString>{{Count = {m_nSize}}}</DisplayString>
</Type>
Parametry šablony v položce vizualizace můžete odkazovat pomocí maker $T 1, $T 2 atd. Příklady těchto maker najdete v souborech .natvis dodávaná se sadou Visual Studio.
Porovnávání typů vizualizéru
Pokud se nepovede ověřit položku vizualizace, použije se další dostupná vizualizace.
Zděděný atribut
Volitelný Inheritable
atribut určuje, zda se vizualizace vztahuje pouze na základní typ, nebo na základní typ a všechny odvozené typy. Výchozí hodnota atributu Inheritable
je true
.
V následujícím příkladu se vizualizace vztahuje pouze na BaseClass
typ:
<Type Name="Namespace::BaseClass" Inheritable="false">
<DisplayString>{{Count = {m_nSize}}}</DisplayString>
</Type>
Atribut Priority
Volitelný Priority
atribut určuje pořadí, ve kterém se mají použít alternativní definice, pokud se definice nepodaří analyzovat. Možné hodnoty Priority
jsou: Low
, , MediumLow
Medium
, MediumHigh
a High
. Výchozí hodnota je Medium
. Atribut Priority
rozlišuje pouze priority ve stejném souboru .natvis .
Následující příklad nejprve analyzuje položku, která odpovídá hodnotě STL 2015. Pokud se to nepodaří analyzovat, použije alternativní položku pro verzi STL 2013:
<!-- 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>
Volitelný atribut
Atribut můžete umístit Optional
na libovolný uzel. Pokud se dílčí výraz uvnitř volitelného uzlu nepodaří analyzovat, ladicí program tento uzel ignoruje, ale použije zbytek Type
pravidel. V následujícím typu [State]
není volitelný, ale [Exception]
je nepovinný. Pokud MyNamespace::MyClass
má pole s názvem _M_exceptionHolder
, [State]
zobrazí se uzel i [Exception]
uzel, ale pokud neexistuje žádné _M_exceptionHolder
pole, zobrazí se pouze [State]
uzel.
<Type Name="MyNamespace::MyClass">
<Expand>
<Item Name="[State]">_M_State</Item>
<Item Name="[Exception]" Optional="true">_M_exceptionHolder</Item>
</Expand>
</Type>
Atribut podmínky
Volitelný Condition
atribut je k dispozici pro mnoho prvků vizualizace a určuje, kdy se má použít pravidlo vizualizace. Pokud se výraz uvnitř atributu podmínky přeloží na false
, pravidlo vizualizace se nepoužije. Pokud se vyhodnotí jako true
nebo neexistuje žádný Condition
atribut, vizualizace se použije. Tento atribut můžete použít pro logiku if-else v položkách vizualizace.
Například následující vizualizace obsahuje dva DisplayString
prvky pro typ inteligentního ukazatele. _Myptr
Když je člen prázdný, podmínka prvního DisplayString
prvku se přeloží na true
, aby se formulář zobrazil. _Myptr
Pokud člen není prázdný, podmínka se vyhodnotí jako false
a druhý DisplayString
prvek se zobrazí.
<Type Name="std::auto_ptr<*>">
<DisplayString Condition="_Myptr == 0">empty</DisplayString>
<DisplayString>auto_ptr {*_Myptr}</DisplayString>
<Expand>
<ExpandedItem>_Myptr</ExpandedItem>
</Expand>
</Type>
Atributy IncludeView a ExcludeView
ExcludeView
Atributy IncludeView
určují prvky, které se mají zobrazit nebo nezobrazují v konkrétních zobrazeních. Například v následující specifikaci std::vector
Natvis zobrazení simple
nezobrazuje [size]
a [capacity]
položky.
<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>
Můžete použít IncludeView
atributy pro ExcludeView
typy a jednotlivé členy.
Prvek verze
Element Version
definuje položku vizualizace na konkrétní modul a verzi. Tento Version
prvek pomáhá vyhnout se kolizím názvů, snižuje neúmyslné neshody a umožňuje různé vizualizace pro různé verze typů.
Pokud společný hlavičkový soubor, který používá různé moduly, definuje typ, zobrazí se vizualizace s verzí pouze v případě, že je typ v zadané verzi modulu.
V následujícím příkladu je vizualizace použitelná pouze pro DirectUI::Border
typ nalezený ve Windows.UI.Xaml.dll
verzi 1.0 až 1.5.
<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>
Nepotřebujete obojí Min
a Max
. Jedná se o volitelné atributy. Nepodporují se žádné zástupné znaky.
Atribut Name
je ve formátu filename.ext, například hello.exe nebo some.dll. Nejsou povoleny žádné názvy cest.
DisplayString – element
Element DisplayString
určuje řetězec, který se má zobrazit jako hodnota proměnné. Přijímá libovolné řetězce smíšené s výrazy. Vše uvnitř složených závorek se interpretuje jako výraz. Například následující DisplayString
položka:
<Type Name="CPoint">
<DisplayString>{{x={x} y={y}}}</DisplayString>
</Type>
Znamená, že proměnné typu CPoint
se zobrazují jako na tomto obrázku:
Ve výrazu DisplayString
x
a y
, které jsou členy CPoint
, jsou uvnitř složených závorek, takže jejich hodnoty jsou vyhodnoceny. Příklad také ukazuje, jak můžete utéct složenou závorku pomocí dvojitých složených závorek ( {{
nebo }}
).
Poznámka:
Element DisplayString
je jediný prvek, který přijímá libovolné řetězce a složené závorky syntaxe. Všechny ostatní prvky vizualizace přijímají pouze výrazy, které ladicí program může vyhodnotit.
StringView – element
Element StringView
definuje hodnotu, kterou ladicí program může odeslat do integrovaného vizualizéru textu. Například vzhledem k následující vizualizaci pro ATL::CStringT
typ:
<Type Name="ATL::CStringT<wchar_t,*>">
<DisplayString>{m_pszData,su}</DisplayString>
</Type>
Objekt CStringT
se zobrazí v okně proměnné jako v tomto příkladu:
Přidání elementu StringView
říká ladicímu programu, že může zobrazit hodnotu jako textovou vizualizaci.
<Type Name="ATL::CStringT<wchar_t,*>">
<DisplayString>{m_pszData,su}</DisplayString>
<StringView>m_pszData,su</StringView>
</Type>
Během ladění můžete vybrat ikonu lupy vedle proměnné a pak vybrat Vizualizér textu a zobrazit řetězec, na který m_pszData odkazuje.
Výraz {m_pszData,su}
obsahuje specifikátor formátu jazyka C++, který zobrazí hodnotu jako řetězec Unicode. Další informace naleznete v tématu Specifikátory formátu v jazyce C++.
Expand – element
Volitelný Expand
uzel přizpůsobí podřízené položky vizualizovaného typu při rozbalení typu v okně proměnné. Uzel Expand
přijímá seznam podřízených uzlů, které definují podřízené prvky.
Expand
Pokud uzel není zadaný v položce vizualizace, podřízené položky používají výchozí pravidla rozšíření.Expand
Pokud je uzel zadaný bez podřízených uzlů, typ není v oknech ladicího programu rozbalitelný.
Rozšíření položky
Prvek Item
je nejzásadnější a nejběžnější prvek v Expand
uzlu. Item
definuje jeden podřízený prvek. Například CRect
třída s poli top
, left
, right
a bottom
má následující položku vizualizace:
<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>
V okně ladicího programu vypadá typ jako v tomto příkladu CRect
:
Ladicí program vyhodnotí výrazy zadané v Width
elementech a Height
zobrazí hodnoty ve sloupci Hodnota v okně proměnné.
Ladicí program automaticky vytvoří uzel [Nezpracované zobrazení] pro každé vlastní rozšíření. Předchozí snímek obrazovky zobrazuje rozbalený uzel [Nezpracované zobrazení] a ukazuje, jak se výchozí nezpracované zobrazení objektu liší od vizualizace Natvis. Výchozí rozšíření vytvoří podstrom základní třídy a vypíše všechny datové členy základní třídy jako podřízené položky.
Poznámka:
Pokud výraz prvku položky odkazuje na komplexní typ, uzel Item samotný je rozbalitelný.
Rozšíření ArrayItems
ArrayItems
Pomocí uzlu můžete ladicí program sady Visual Studio interpretovat typ jako pole a zobrazit jeho jednotlivé prvky. std::vector
Vizualizace je dobrým příkladem:
<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>
Při rozbalení v okně proměnné se std::vector
zobrazí jeho jednotlivé prvky:
Uzel ArrayItems
musí mít:
- Výraz
Size
(který musí být vyhodnocen jako celé číslo) pro ladicí program, aby porozuměl délce pole. - Výraz
ValuePointer
, který odkazuje na první prvek (což musí být ukazatel typu prvku, který nenívoid*
).
Výchozí hodnota dolní hranice pole je 0. K přepsání hodnoty použijte LowerBound
prvek. Soubory .natvis dodávané se sadou Visual Studio obsahují příklady.
Poznámka:
Operátor můžete použít []
například vector[i]
s libovolnou vizualizací jednorozměrného pole, která používá ArrayItems
, i když samotný typ (například CATLArray
) tento operátor nepovoluje.
Můžete také zadat vícerozměrná pole. V takovém případě ladicí program potřebuje k správnému zobrazení podřízených prvků o něco více informací:
<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
určuje, jestli je pole v pořadí hlavního řádku nebo hlavního sloupce.Rank
určuje pořadí pole.- Element
Size
přijímá implicitní$i
parametr, který nahradí indexem dimenze, aby zjistil délku pole v této dimenzi.- V předchozím příkladu by výraz
_M_extent.M_base[0]
měl dát délku 0. dimenze,_M_extent._M_base[1]
první a tak dále.
- V předchozím příkladu by výraz
- Určuje
LowerBound
dolní mez každé dimenze pole. U multidimenzionálních polí můžete zadat výraz, který používá implicitní$i
parametr. Parametr$i
bude nahrazen indexem dimenze, aby našel dolní mez pole v dané dimenzi.- V předchozím příkladu budou všechny dimenze začínat na 0. Pokud byste však měli
($i == 1) ? 1000 : 100
dolní mez, začne 0. dimenze na 100 a první dimenze začne na 1000.- Například
[100, 1000], [100, 1001], [100, 1002], ... [101, 1000], [101, 1001],...
- Například
- V předchozím příkladu budou všechny dimenze začínat na 0. Pokud byste však měli
V okně ladicího programu vypadá dvojrozměrný Concurrency::array
objekt:
Rozšíření IndexListItems
Rozšíření lze použít ArrayItems
pouze v případě, že jsou prvky pole rozloženy souvisle v paměti. Ladicí program se dostane k dalšímu prvku jednoduchým zvýšením ukazatele. Pokud potřebujete manipulovat s indexem uzlu hodnoty, použijte IndexListItems
uzly. Tady je vizualizace s IndexListItems
uzlem:
<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>
Jediný rozdíl mezi a je , který očekává úplný výraz na ith element s implicitní $i
parametr.ValueNode
IndexListItems
ArrayItems
Poznámka:
Operátor můžete použít []
například vector[i]
s libovolnou vizualizací jednorozměrného pole, která používá IndexListItems
, i když samotný typ (například CATLArray
) tento operátor nepovoluje.
Rozšíření LinkedListItems
Pokud vizualizovaný typ představuje propojený seznam, může ladicí program zobrazit podřízené položky pomocí LinkedListItems
uzlu. Následující vizualizace pro CAtlList
typ používá 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>
Prvek Size
odkazuje na délku seznamu. HeadPointer
odkazuje na první prvek, NextPointer
odkazuje na další prvek a ValueNode
odkazuje na hodnotu položky.
Ladicí program vyhodnotí NextPointer
výrazy a ValueNode
výrazy v kontextu LinkedListItems
prvku uzlu, nikoli nadřazeného typu seznamu. V předchozím příkladu CAtlList
má CNode
třídu (nalezenou v atlcoll.h
) , která je uzlem propojeného seznamu. m_pNext
a m_element
jsou pole této CNode
třídy, nikoli CAtlList
třídy.
ValueNode
může být ponechána prázdná nebo se používá this
k odkazování na LinkedListItems
samotný uzel.
Rozšíření CustomListItems
Rozšíření CustomListItems
umožňuje napsat vlastní logiku pro procházení datové struktury, jako je například hashtable. Umožňuje CustomListItems
vizualizovat datové struktury, které můžou používat výrazy jazyka C++ pro všechno, co potřebujete k vyhodnocení, ale nevejde se do formy pro ArrayItems
, IndexListItems
nebo LinkedListItems
.
Můžete použít Exec
ke spuštění kódu uvnitř CustomListItems
rozšíření pomocí proměnných a objektů definovaných v rozšíření. Můžete použít logické operátory, aritmetické operátory a operátory přiřazení s Exec
. Nemůžete použít Exec
k vyhodnocení funkcí, s výjimkou vnitřních funkcí ladicího programu podporovaných vyhodnocovačem výrazů jazyka C++.
Následující vizualizér CAtlMap
je skvělým příkladem, kde CustomListItems
je to vhodné.
<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>
Rozšíření TreeItems
Pokud vizualizovaný typ představuje strom, ladicí program může strom procházet a zobrazit jeho podřízené položky pomocí TreeItems
uzlu. Tady je vizualizace typu std::map
pomocí TreeItems
uzlu:
<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>
Syntaxe je podobná LinkedListItems
uzlu. LeftPointer
, RightPointer
a ValueNode
jsou vyhodnoceny v kontextu třídy uzlu stromu. ValueNode
může být ponechána prázdná nebo použít this
k odkazování na TreeItems
samotný uzel.
Rozšíření ExpandedItem
Element ExpandedItem
generuje agregované podřízené zobrazení zobrazení zobrazením vlastností základních tříd nebo datových členů, jako by šlo o podřízené prvky vizualizovaného typu. Ladicí program vyhodnotí zadaný výraz a připojí podřízené uzly výsledku do podřízeného seznamu vizualizovaného typu.
Například typ auto_ptr<vector<int>>
inteligentního ukazatele se obvykle zobrazuje takto:
Pokud chcete zobrazit hodnoty vektoru, musíte přejít k podrobnostem o dvou úrovních v okně proměnné a procházet členem _Myptr
. Přidáním elementu _Myptr
můžete eliminovat proměnnou ExpandedItem
z hierarchie a přímo zobrazit vektorové prvky:
<Type Name="std::auto_ptr<*>">
<DisplayString>auto_ptr {*_Myptr}</DisplayString>
<Expand>
<ExpandedItem>_Myptr</ExpandedItem>
</Expand>
</Type>
Následující příklad ukazuje, jak agregovat vlastnosti ze základní třídy v odvozené třídě. Předpokládejme, že CPanel
třída je odvozena od CFrameworkElement
. Místo opakování vlastností, které pocházejí ze základní CFrameworkElement
třídy, ExpandedItem
připojí vizualizace uzlu tyto vlastnosti do podřízeného CPanel
seznamu třídy.
<Type Name="CPanel">
<DisplayString>{{Name = {*(m_pstrName)}}}</DisplayString>
<Expand>
<Item Name="IsItemsHost">(bool)m_bItemsHost</Item>
<ExpandedItem>*(CFrameworkElement*)this,nd</ExpandedItem>
</Expand>
</Type>
Zde je nezbytný specifikátor formátu nd , který vypne vizualizaci odpovídající odvozené třídě. Jinak by výraz *(CFrameworkElement*)this
způsobil CPanel
opětovné použití vizualizace, protože výchozí pravidla párování typů vizualizací považují za nejvhodnější. Specifikátor formátu nd použijte k pokynu ladicímu programu, aby používal vizualizaci základní třídy, nebo výchozí rozšíření, pokud základní třída nemá žádnou vizualizaci.
Rozšíření syntetických položek
ExpandedItem
I když prvek poskytuje ploché zobrazení dat odstraněním hierarchií, Synthetic
uzel dělá opak. Umožňuje vytvořit umělý podřízený prvek, který není výsledkem výrazu. Umělý prvek může mít vlastní podřízené prvky. V následujícím příkladu vizualizace pro Concurrency::array
typ používá Synthetic
uzel k zobrazení diagnostické zprávy uživateli:
<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>
Instrinsic expand
Vlastní vnitřní funkce, kterou lze volat z výrazu. Prvek <Intrinsic>
musí být doprovázen komponentou ladicího programu, která implementuje funkci prostřednictvím rozhraní IDkmIntrinsicFunctionEvaluator140.
<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
Element HResult
umožňuje přizpůsobit informace zobrazené pro HRESULT v oknech ladicího programu. Prvek HRValue
musí obsahovat 32bitovou hodnotu HRESULT , která se má přizpůsobit. Element HRDescription
obsahuje informace, které se mají zobrazit v okně ladicího programu.
<HResult Name="MY_E_COLLECTION_NOELEMENTS">
<HRValue>0xABC0123</HRValue>
<HRDescription>No elements in the collection.</HRDescription>
</HResult>
UIVisualizer – element
Prvek UIVisualizer
zaregistruje modul plug-in grafického vizualizéru s ladicím programem. Grafický vizualizér vytvoří dialogové okno nebo jiné rozhraní, které zobrazuje proměnnou nebo objekt způsobem konzistentním s jeho datovým typem. Modul plug-in vizualizéru musí být vytvořený jako balíček VSPackage a musí vystavit službu, kterou může ladicí program využívat. Soubor .natvis obsahuje informace o registraci modulu plug-in, jako je jeho název, globálně jedinečný identifikátor (GUID) vystavené služby a typy, které může vizualizovat.
Tady je příklad elementu UIVisualizer:
<?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>
Pár
ServiceId
-Id
atributů identifikujeUIVisualizer
hodnotu . Jedná seServiceId
o identifikátor GUID služby, který balíček vizualizéru zveřejňuje.Id
je jedinečný identifikátor, který rozlišuje vizualizéry, pokud služba poskytuje více než jeden. V předchozím příkladu poskytuje stejná služba vizualizéru dva vizualizéry.Atribut
MenuName
definuje název vizualizéru, který se zobrazí v rozevíracím seznamu vedle ikony lupy v ladicím programu. Příklad:
Každý typ definovaný v souboru .natvis musí explicitně zobrazit všechny vizualizéry uživatelského rozhraní, které ho mohou zobrazit. Ladicí program odpovídá odkazům vizualizéru v položkách typu s registrovanými vizualizéry. Například následující položka typu pro std::vector
odkazy UIVisualizer
v předchozím příkladu.
<Type Name="std::vector<int,*>">
<UIVisualizer ServiceId="{5452AFEA-3DF6-46BB-9177-C0B08F318025}" Id="1" />
</Type>
Můžete vidět příklad UIVisualizer
rozšíření Image Watch použité k zobrazení rastrových obrázků v paměti.
CustomVisualizer – element
CustomVisualizer
je bod rozšiřitelnosti, který určuje rozšíření VSIX, které napíšete pro řízení vizualizací v editoru Visual Studio Code. Další informace o psaní rozšíření VSIX najdete v sadě Visual Studio SDK.
Je mnohem více práce napsat vlastní vizualizér než definice Natvis XML, ale nemáte omezení ohledně toho, co Natvis dělá nebo nepodporuje. Vlastní vizualizéry mají přístup k úplné sadě rozhraní API rozšiřitelnosti ladicího programu, která můžou dotazovat a upravovat proces ladění nebo komunikovat s jinými částmi sady Visual Studio.
U elementů můžete použít Condition
atributy , IncludeView
a ExcludeView
atributy.CustomVisualizer
Omezení
Vlastní nastavení Natvis pracují s třídami a strukturami, ale ne typedefs.
Natvis nepodporuje vizualizéry pro primitivní typy (například int
, bool
), ani pro ukazatele na primitivní typy. V tomto scénáři je jednou z možností použití specifikátoru formátu vhodného pro váš případ použití. Pokud například používáte double* mydoublearray
v kódu, můžete použít specifikátor formátu pole v okně Kukátko ladicího programu, například výraz mydoublearray, [100]
, který zobrazuje prvních 100 prvků.