Displaying idLib types nicely in MSVC debugger: Difference between revisions

From The DarkMod Wiki
Jump to navigationJump to search
(Rewrote the whole article: MSVC2013 update.)
Line 1: Line 1:
==Extra-short summary==
==Custom visualizers==


The MSVS can be configured to show TDM objects (mostly idLib containers) nicely in the watch. To benefit from it you have to follow the instructions located in:
The MSVS can be configured to show TDM objects nicely in the watch using custom rules.
  \darkmod_src\tools\autoexp\
As a result, you can directly expand e.g. idList, idLinkList or idDict to see all its elements.
directory inside the darkmod_src SVN repo.
Also, you can expand idEntityPtr to see the entity you it references.
These rules greatly facilitate MSVC debugging.


==Introduction==
===Installation===


In Visual Studio debugger you can see the value of any variable by either adding it to watch or holding a mouse cursor over it. Unfortunately, the information is often shown in uncomfortable way. If you want to watch the contents of an array, you'll likely see only the first element by default. If you watch the contests of an objects, you'll see all of its members, which is not nice in case the object represents a container.
Currently all the TDM-specific rules are defined in <code>/tools/natvis/*.natvis</code> files in the SVN repo.
These files are '''automatically copied''' into <code>%USERPROFILE%\Documents\Visual Studio 2013\Visualizers\</code> on each build,
so you don't even have to do anything to make them work.
Note that they are never deleted from the target directory, so if they disturb you in future, you have to delete them manually.


Luckily, these problems can be easily solved.
The source code also heavily uses ''boost'' library.
In order to watch boost containers, you should '''install extension''' [https://marketplace.visualstudio.com/items?itemName=ArkadyShapkin.CDebuggerVisualizersforVS2013 "C++ Debugger Visualizers for VS2013"].
Here are the steps to install the extension:


==Watching arrays==
# Go to menu Tools->Extensions and Updates.
# Click on Online on the left pane to get to Visual Studio Gallery.
# Type "Debugger Visualizers" into the search bar in the top-right corner.
# Choose the extension, click on Download, then on Install.
# Finally, click on Restart Now button to load the extension.


If you need to watch static-sized array (like "int arr[256];"), then by default all the 256 elements are shown in the watch. But in TDM you'll mostly come across dynamically allocated arrays (like "int *arr = new int[256];"). In this case debugger has no way to know the size of array, that's why it shows only one element. You can manually specify how many elements of the array to display for the pointer. Just type in the watch:
===Usage===


  arr,240
Here are an example showing how the data looks like:


and you'll see exactly 240 first elements of the array.
[[Image:natvis_tdm_example.png]]


==Watching custom objects==
Note that if you expand a value with a properly working custom visualizer, you will always see <code>[Raw View]</code> as the last item in it. If you expand it, then you will see the contents of the value visualized using built-in rules of the debugger (i.e. without custom visualizer applied). This is very helpful if you need to see the exact internals of a value.


By default any object in watch is displayed as a collection of its members. Generally it is good enough. But if the object is a commonly used container (like "idList<int> v;") then you have to type "v.list,100" each time you want to see considerable quantity of its elements.
Also, you can suppress custom visualizers by adding a special suffix in a watch.
For instance, if you have variable <code>idList<idEntity*> corrupted</code>, which you suspect is corrupted, then you can see its exact internals by typing <code>corrupted,!</code> into the watch.


This problem is almost identical for idLib, STL and boost containers. But since STL is integrated into the C++ language, MSVC displays all the STL containers in a nice way. This feature is implemented via the "autoexp.dat" config file inside the MSVS installation. Luckily, we can add our own templates to this file to customize the way objects of our classes are displayed. The "autoexp.dat" file is very scarcely documented by Microsoft. The only comprehensive piece of documentation is this article:
Sometimes it might be useful to display data using customized ''view''. For instance, if you use the "simple" view, then std::vector would have no [size] and [capacity] when expanded, and idLinkList would have no [Enum All] and [Enum Close] when expanded.


http://www.virtualdub.org/blog/pivot/entry.php?id=120
==General tricks==


The up-to-date templates for TDM project are located in "darkmod_src\tools\autoexp\" directory inside darkmod_src SVN repository. The installation readme is located there too. By installing the templates you'll get comfortable view of the following idLib containers:
===Watching arrays===


#idStr - the string itself is displayed in the preview:    [[Image:Autoexp_IdStr.png]]
If you need to watch static-sized array (like <code>int arr[256]</code>), then by default all the 256 elements are shown in the watch. But in TDM you'll mostly come across dynamically allocated arrays (like <code>int *arr = new int[256]</code>). In this case debugger has no way to know the size of array, that's why it shows only one element. You can manually specify how many elements of the array to display for the pointer. Just type <code>arr,240</code> into the watch, and you'll see exactly 240 first elements of the array.
#idList, idStaticList - they look and behave almost like std::vector now: all the actual elements are shown[[Image:Autoexp_IdList.png]]
#idKeyValue, idDict - they can be watched as an array of key/value pairs in convenient way:  [[Image:Autoexp_IdDict.png]]


The appearance of idHashIndex container is improved a bit, but it is still far from perfect. idLinkList is not implemented: autoexp is familiar with linked lists, but it doesn't want to swallow idLinkList for some reason...
===Suppressing the autoexp templates===
Suppose that you have a list "idList<int> corrupted;" and you suspect that it is corrupted. You need to see all its members in this case. To see them you need only to add ",!" when you type the object into the watch:
  corrupted,!


[[Category:coding]]
[[Category:coding]]
[[Category:SDK]]
[[Category:SDK]]

Revision as of 14:52, 1 April 2017

Custom visualizers

The MSVS can be configured to show TDM objects nicely in the watch using custom rules. As a result, you can directly expand e.g. idList, idLinkList or idDict to see all its elements. Also, you can expand idEntityPtr to see the entity you it references. These rules greatly facilitate MSVC debugging.

Installation

Currently all the TDM-specific rules are defined in /tools/natvis/*.natvis files in the SVN repo. These files are automatically copied into %USERPROFILE%\Documents\Visual Studio 2013\Visualizers\ on each build, so you don't even have to do anything to make them work. Note that they are never deleted from the target directory, so if they disturb you in future, you have to delete them manually.

The source code also heavily uses boost library. In order to watch boost containers, you should install extension "C++ Debugger Visualizers for VS2013". Here are the steps to install the extension:

  1. Go to menu Tools->Extensions and Updates.
  2. Click on Online on the left pane to get to Visual Studio Gallery.
  3. Type "Debugger Visualizers" into the search bar in the top-right corner.
  4. Choose the extension, click on Download, then on Install.
  5. Finally, click on Restart Now button to load the extension.

Usage

Here are an example showing how the data looks like:

Natvis tdm example.png

Note that if you expand a value with a properly working custom visualizer, you will always see [Raw View] as the last item in it. If you expand it, then you will see the contents of the value visualized using built-in rules of the debugger (i.e. without custom visualizer applied). This is very helpful if you need to see the exact internals of a value.

Also, you can suppress custom visualizers by adding a special suffix in a watch. For instance, if you have variable idList<idEntity*> corrupted, which you suspect is corrupted, then you can see its exact internals by typing corrupted,! into the watch.

Sometimes it might be useful to display data using customized view. For instance, if you use the "simple" view, then std::vector would have no [size] and [capacity] when expanded, and idLinkList would have no [Enum All] and [Enum Close] when expanded.

General tricks

Watching arrays

If you need to watch static-sized array (like int arr[256]), then by default all the 256 elements are shown in the watch. But in TDM you'll mostly come across dynamically allocated arrays (like int *arr = new int[256]). In this case debugger has no way to know the size of array, that's why it shows only one element. You can manually specify how many elements of the array to display for the pointer. Just type arr,240 into the watch, and you'll see exactly 240 first elements of the array.