Poznámka
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Architektura Natvis platformy Visual Studio
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í se třídami a strukturami, ale ne s typedefy.
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 ukazuje proměnnou typu Windows::UI::XAML::Controls::TextBox v okně ladicího programu bez použití vlastních vizualizací.
Zvýrazněný řádek zobrazuje vlastnost Text
třídy TextBox
. 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
vypadá v okně proměnných mnohem jednodušeji, když jsou použita vlastní pravidla 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á k určení pravidel vizualizace soubory .natvis. Soubor .natvis je soubor XML s příponou .natvis. Schéma Natvis je definováno v instalační složce <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 prvku Type
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íku řešenía vyberte Project>Přidat novou položku, nebo klikněte pravým tlačítkem myši na projekt a vyberte Přidat>Nová položka.
Pokud nevidíte všechny šablony položek, zvolte Zobrazit všechny šablony.
V dialogovém okně Přidat novou položku vyberte Visual C++>Utility>vizualizační soubor ladicího programu (.natvis).
Pojmenujte soubor a vyberte Přidat.
Nový soubor se přidá do Průzkumníka ř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ž nemáte projekt otevřený. Pokud nechcete, aby byl soubor .natvis zahrnutý v .pdb, můžete jej vyloučit ze sestaveného 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.
Klikněte na šipku vedle Excluded From Build a vyberte Ano, a poté vyberte OK.
Poznámka
Pro ladění spustitelných projektů pomocí položek řešení přidejte všechny soubory .natvis, které nejsou v .pdb, protože neexistuje žádný projekt C++.
Poznámka
Pravidla Natvis načtená z .pdb se vztahují pouze na typy v modulech, na které .pdb odkazuje. Pokud má například Module1.pdb položku Natvis pro typ pojmenovaný Test
, vztahuje se pouze na třídu Test
v Module1.dll. Pokud jiný modul také definuje třídu s názvem Test
, Module1.pdb položka Natvis se na ni nevztahuje.
Instalace a registrace souboru .natvis prostřednictvím balíčku VSIX:
Balíček VSIX může nainstalovat a zaregistrovat soubory .natvis. Bez ohledu na to, kde jsou nainstalovány, všechny registrované .natvis soubory jsou automaticky načteny během ladění.
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, které jsou vloženy do .pdb během ladění, pokud v načteném projektu neexistuje soubor se stejným názvem.
Všechny .natvis soubory načtené do projektu C++ nebo do ř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 .natvis soubory 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).
- Systémový adresář Natvis (<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ží, okna Watch a Locals se aktualizují, aby se změna projevila.
V řešení, které ladíte, můžete také přidat nebo odstranit soubory .natvis 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 Okamžitém okně . Změny se pak projeví bez restartování relace ladění.
Pomocí příkazu .natvisreload také upgradujte soubor .natvis na novější verzi. 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 nástroji, která jsou popsána v kontextový operátor (C++), mějte na paměti následující:
Výrazy Natvis se vyhodnocují v kontextu vizualizovaného objektu, nikoli v aktuálním zásobníkovém rámci. Například
x
ve výrazu Natvis odkazuje na pole s názvem 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í. Protože intrinsické funkce debuggeru jsou bez vedlejších účinků, mohou být volně volány z jakéhokoli výrazu Natvis, přestože jiná volání funkcí jsou zakázána.
Chcete-li řídit způsob zobrazení výrazu, můžete použít libovolný specifikátor formátu popsaný v částce Specifikátory formátu v C++. Specifikátory formátu se ignorují, když se položka používá interně v rámci Natvis, například výraz
Size
v expanzi ArrayItems .
Poznámka
Vzhledem k tomu, že dokument Natvis je formátu XML, nemohou vaše výrazy přímo použít znak ampersand, větší než, menší než nebo operátory posunu. Tyto znaky je nutné escapovat jak v těle položky, tak v podmínkových výrazech. Napří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
a ArrayItems
se zobrazují ve výchozím zobrazení a v zobrazení simple
, zatímco položky [size]
a [capacity]
se v zobrazení simple
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ě Sledování použijte specifikátor formátu ,zobrazení k zadání alternativního zobrazení. Jednoduché zobrazení se zobrazí jako vec,view(simple):
okno
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 Tools>Options (nebo Debug>Options) >Debugging>Output Windownastavte Natvis diagnostické zprávy (C++ Pouze) na Chyba, Upozorněnínebo Podrobnéa poté vyberte OK.
Chyby se zobrazí v okně Výstup .
Referenční příručka pro syntaxi Natvis
Následující prvky a atributy lze použít v souboru Natvis.
AutoVisualizer prvek
Element AutoVisualizer
je kořenovým uzlem 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 mít podřízené prvky typu, HResult, UIVisualizera CustomVisualizer.
Typ elementu
Základní Type
vypadá jako v tomto příkladu:
<Type Name="[fully qualified type name]">
<DisplayString Condition="[Boolean expression]">[Display value]</DisplayString>
<Expand>
...
</Expand>
</Type>
Element Type
určuje:
Jaký typ vizualizace se má použít (atribut
Name
).Jak by měla vypadat hodnota objektu daného typu (prvek
DisplayString
).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 tříd šablon.
V následujícím příkladu se používá stejná vizualizace, zda je objekt CAtlArray<int>
nebo CAtlArray<float>
. Pokud pro CAtlArray<float>
existuje určitá položka 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 použít pomocí maker $T1, $T2 atd. Příklady těchto maker najdete v souborů .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ý atribut Inheritable
určuje, zda se vizualizace vztahuje pouze na základní typ, nebo na základní typ a všechny odvozené typy. Výchozí hodnota Inheritable
je true
.
V následujícím příkladu se vizualizace vztahuje pouze na typ BaseClass
:
<Type Name="Namespace::BaseClass" Inheritable="false">
<DisplayString>{{Count = {m_nSize}}}</DisplayString>
</Type>
Atribut Priorita
Volitelný atribut Priority
určuje pořadí, ve kterém se mají použít alternativní definice, pokud se definici 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 Optional
můžete umístit na libovolný uzel. Pokud se dílčí výraz uvnitř volitelného uzlu nepodaří analyzovat, ladicí program tento uzel ignoruje, ale použije zbytek pravidel Type
. V následujícím typu [State]
není volitelný, ale [Exception]
je nepovinný. Pokud má MyNamespace::MyClass
pole s názvem _M_exceptionHolder
, zobrazí se uzel [State]
i uzel [Exception]
, ale pokud neexistuje žádné pole _M_exceptionHolder
, zobrazí se pouze uzel [State]
.
<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ý atribut Condition
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ý atribut Condition
, 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 prvky DisplayString
pro typ inteligentního ukazatele. Když je _Myptr
člen prázdný, podmínka prvního prvku DisplayString
se přeloží na true
, aby se formulář zobrazil. Pokud _Myptr
člen není prázdný, podmínka se vyhodnotí jako false
a druhý prvek DisplayString
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
Atributy IncludeView
a ExcludeView
určují prvky, které se mají zobrazit nebo nezobrazují v konkrétních zobrazeních. Například v následující specifikaci Natvis std::vector
zobrazení simple
nezobrazuje položky [size]
a [capacity]
.
<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 typů a jednotlivých členů můžete použít atributy IncludeView
a ExcludeView
.
Součást verze
Element Version
vymezuje položku vizualizace na konkrétní modul a verzi. Prvek Version
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 typ DirectUI::Border
nalezený v Windows.UI.Xaml.dll
verze 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 Min
ani Max
. Jedná se o volitelné atributy. Nepodporují se žádné zástupné znaky.
Atribut Name
je ve formátu název_souboru.ext, například hello.exe nebo some.dll. Nejsou povoleny žádné názvy cest.
DisplayString prvek
Prvek 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
jsou zobrazeny jako na tomto obrázku:
Ve výrazu DisplayString
jsou x
a y
, které jsou členy CPoint
, umístěné v složených závorkách, takže jejich hodnoty se vyhodnotí. Příklad také ukazuje, jak můžete eskapovat složené závorky pomocí dvou složených závorek ({{
nebo }}
).
Poznámka
Prvek DisplayString
je jediný prvek, který přijímá libovolné řetězce a syntaxi složených závorek. 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 typ ATL::CStringT
:
<Type Name="ATL::CStringT<wchar_t,*>">
<DisplayString>{m_pszData,su}</DisplayString>
</Type>
Objekt CStringT
se zobrazí v okně proměnné, jako je tento příklad:
Přidání StringView
elementu ří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 poté vybrat Vizualizér textu, abyste zobrazili řetězec, na který odkazuje m_pszData.
Výraz {m_pszData,su}
obsahuje specifikátor formátu C++ su, aby se hodnota zobrazila jako řetězec Unicode. Další informace naleznete v tématu Specifikátory formátu v jazyce C++.
Rozbalit prvek
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.
Pokud v položce vizualizace není zadaný uzel
Expand
, použijí podřízené položky výchozí pravidla rozšíření.Pokud je zadaný uzel
Expand
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 třída CRect
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 CRect
takto:
Ladicí program vyhodnotí výrazy zadané v prvcích Width
a Height
a zobrazí hodnoty ve sloupci Hodnota v okně s proměnnými.
Ladicí program automaticky vytvoří uzel [Surový pohled] pro každé vlastní rozšíření. Předchozí snímek obrazovky zobrazuje uzel [Nezpracované zobrazení] v rozbaleném stavu, aby bylo zřejmé, jak se výchozí nezpracované zobrazení objektu liší od jeho vizualizace pomocí 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, Item uzel je rozbalitelný.
Rozšíření položek Array
Použijte uzel ArrayItems
k tomu, aby ladicí program sady Visual Studio interpretovala typ jako pole a zobrazila jeho jednotlivé prvky. Příklad vizualizace pro std::vector
:
<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>
std::vector
zobrazí jednotlivé prvky při rozbalení v okně proměnné:
Uzel ArrayItems
musí mít:
- Výraz
Size
(který musí být vyhodnocen jako celé číslo), aby ladicí program 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 prvek LowerBound
. Soubory .natvis dodávané se sadou Visual Studio obsahují příklady.
Poznámka
Můžete použít operátor []
, například vector[i]
, s libovolnou jednorozměrnou maticovou vizualizací, která používá ArrayItems
, i když samotný typ (například CATLArray
) neumožňuje tento operátor.
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 řádkovém nebo sloupcovém uspořádání. -
Rank
určuje pořadí pole. - Element
Size
přijímá implicitní$i
parametr, který nahradí indexem dimenze, aby zjistil délku pole v dané 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
-
LowerBound
určuje 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, který najde dolní mez pole v této dimenzi.- V předchozím příkladu budou všechny dimenze začínat na 0. Pokud jste však měli
($i == 1) ? 1000 : 100
jako 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 jste však měli
V okně ladění vypadá dvojrozměrný objekt Concurrency::array
takto:
Rozšíření seznamu položek indexu
Rozšíření ArrayItems
lze použít pouze v případě, že jsou prvky pole rozloženy souvisle v paměti. Ladicí program se dostane k dalšímu prvku pouhým zvýšením pointeru. 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ým rozdílem mezi ArrayItems
a IndexListItems
je ValueNode
, který očekává úplný výraz pro i-týprvek s implicitním parametrem $i
.
Poznámka
Můžete použít operátor []
, například vector[i]
, s libovolnou jednorozměrnou maticovou vizualizací, která používá IndexListItems
, i když samotný typ (například CATLArray
) neumožňuje tento operátor.
Rozšíření položek LinkedList
Pokud vizualizovaný typ představuje propojený seznam, může ladicí program zobrazit podřízené položky pomocí uzlu LinkedListItems
. Následující vizualizace pro typ CAtlList
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í výrazy NextPointer
a ValueNode
v kontextu elementu LinkedListItems
node, nikoli nadřazeného typu seznamu. V předchozím příkladu má CAtlList
třídu CNode
(nalezenou v atlcoll.h
), která je uzlem propojeného seznamu.
m_pNext
a m_element
jsou pole této třídy CNode
, nikoli třídy CAtlList
.
ValueNode
může být ponechána prázdná nebo pomocí this
odkazovat na samotný uzel LinkedListItems
.
Rozšíření CustomListItems
Rozšíření CustomListItems
umožňuje napsat vlastní logiku pro procházení datové struktury, jako je například hashtable. Pomocí CustomListItems
můžete vizualizovat datové struktury, které mohou používat výrazy jazyka C++ pro veškeré potřebné vyhodnocení, ale ne zcela odpovídají formátům ArrayItems
, IndexListItems
nebo LinkedListItems
.
Pomocí Exec
můžete spustit kód uvnitř rozšíření CustomListItems
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é vyhodnocovačem výrazů jazyka C++.
Následující vizualizér pro CAtlMap
je skvělým příkladem, kde je vhodný CustomListItems
.
<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 zobrazený typ představuje strom, ladicí program může strom procházet a zobrazit jeho potomky pomocí uzlu TreeItems
. 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 se podobá uzlu LinkedListItems
.
LeftPointer
, RightPointer
a ValueNode
se vyhodnocují v kontextu třídy uzlu stromu.
ValueNode
může být ponechána prázdná nebo pomocí this
odkazovat na samotný uzel TreeItems
.
Rozšíření položky ExpandedItem
Element ExpandedItem
generuje agregované podřízené zobrazení tím, že zobrazuje vlastnosti základních tříd nebo datových členů, jako by byly podřízenými prvky vizualizovaného typu. Debugger vyhodnotí zadaný výraz a připojí uzly potomků výsledku do seznamu uzlů potomků vizualizovaného typu.
Například typ inteligentního ukazatele auto_ptr<vector<int>>
obvykle zobrazuje takto:
Pokud chcete zobrazit hodnoty vektoru, musíte se ponořit o dvě úrovně hlouběji v okně proměnné a projít přes prvek _Myptr
. Přidáním ExpandedItem
elementu můžete eliminovat _Myptr
proměnnou 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 třída CPanel
je odvozena od CFrameworkElement
. Namísto opakování vlastností, které pocházejí ze základní CFrameworkElement
třídy, připojí vizualizace ExpandedItem
uzlu tyto vlastnosti do podřízeného seznamu třídy CPanel
.
<Type Name="CPanel">
<DisplayString>{{Name = {*(m_pstrName)}}}</DisplayString>
<Expand>
<Item Name="IsItemsHost">(bool)m_bItemsHost</Item>
<ExpandedItem>*(CFrameworkElement*)this,nd</ExpandedItem>
</Expand>
</Type>
Specifikátory formátu a, které vypnou sladění vizualizace pro odvozenou třídu, jsou zde nezbytné. Jinak by výraz *(CFrameworkElement*)this
způsoboval, že se vizualizace CPanel
aplikovala znovu, protože výchozí pravidla pro porovnávání typů vizualizací ji považují za nejvhodnější. Pomocí specifikátoru nd formátu instruujte ladicí program, 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
I když prvek ExpandedItem
poskytuje ploché zobrazení dat odstraněním hierarchií, Synthetic
uzel dělá opačně. Umožňuje vytvořit umělý podřízený prvek, který nevznikl jako výsledek výrazu. Umělý prvek může mít vlastní podřízené prvky. V následujícím příkladu vizualizace pro typ Concurrency::array
používá uzel Synthetic
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>
Vnitřní rozšíření
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. Další informace o implementaci vlastní vnitřní funkce naleznete v tématu Implementace vlastní vnitřní funkce NatVis.
<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 prvek
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á vlastně upravit. Prvek HRDescription
obsahuje informace k zobrazení v okně ladicího programu.
<HResult Name="MY_E_COLLECTION_NOELEMENTS">
<HRValue>0xABC0123</HRValue>
<HRDescription>No elements in the collection.</HRDescription>
</HResult>
UIVisualizer — prvek
Prvek UIVisualizer
zaregistruje zásuvný modul grafického vizualizéru pro ladicí program. Grafický vizualizér vytvoří dialogové okno nebo jiné rozhraní, které zobrazuje proměnnou nebo objekt způsobem konzistentním s jeho datovým typem. Plug-in vizualizéru musí být vytvořen jako VSPackagea musí nabízet službu, kterou může ladicí program využívat. Soubor .natvis obsahuje registrační informace pro modul plug-in, například 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>
Dvojice atributů
ServiceId
-Id
identifikujeUIVisualizer
.ServiceId
je 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. Například:místní nabídka
Každý typ definovaný v souboru .natvis musí explicitně zobrazit všechny vizualizéry uživatelského rozhraní, které ho mohou zobrazit. Ladicí program porovnává odkazy vizualizeru v položkách typu s registrovanými vizualizéry. Například následující položka typu pro std::vector
odkazuje na UIVisualizer
v předchozím příkladu.
<Type Name="std::vector<int,*>">
<UIVisualizer ServiceId="{5452AFEA-3DF6-46BB-9177-C0B08F318025}" Id="1" />
</Type>
Příklad
Prvek CustomVisualizer
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 naleznete v 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 prvků Condition
můžete použít atributy IncludeView
, ExcludeView
a CustomVisualizer
.
Omezení
Vlastní nastavení Natvis pracují se třídami a strukturami, ale ne s typedefy.
Natvis nepodporuje vizualizéry pro primitivní typy (například int
, bool
) nebo ukazatele na primitivní typy. V tomto scénáři je jednou z možností použít specifikátor formátu vhodný pro váš případ použití. Pokud například ve svém kódu použijete double* mydoublearray
, můžete použít specifikátor formátu pole v okně Kukátko watch, například výraz mydoublearray, [100]
, který zobrazuje prvních 100 prvků.