在Visual Studio 2012中,我们介绍了创建可视化使用原生类型的能力natvis文件。 Visual Studio 2013中包含了一些改进,使其更容易编写可视化的类,在内部利用收集来存储项目。 在这篇博客文章中,我将介绍一个示例场景,告诉你什么是你必须做的VS2012以达到预期的效果,然后告诉你如何在natvis创作变得更容易,体验VS2013新功能的增强。

示例场景

让我们考虑下面的源代码,并假设我们是在写一个可视化的CNameList类:

  #include <vector>
 using namespace std;
 
 class CName
 {
 private:
     string m_first;
     string m_last;
 
 public:
     CName(string first, string last) : m_first(first), m_last(last) {}
 
     void Print()
     { 
         wprintf(L"%s %s\n", (const char*) m_first.c_str(), (const char*) m_last.c_str());
     }
 };
 
 class CNameList
 {
 private:
     vector m_list;
 
 public:
     CNameList() {}
 
     ~CNameList()
     {
         for (int i = 0; i < m_list.size(); i++)
         {
             delete m_list[i];
         }
         m_list.clear();
     }
 
     void AddName(string first, string last)
     {
         m_list.push_back(new CName(first, last));
     }
 
 
 };
 
 int _tmain(int argc, _TCHAR* argv[])
 {
     CNameList presidents;
     presidents.AddName("George", "Washington");
     presidents.AddName("John", "Adams");
     presidents.AddName("Thomas", "Jefferson");
     presidents.AddName("Abraham", "Lincoln");
 
     return 0;
 }

CNameList可视化工具

在Visual Studio 2012中,它可能会非常棘手,有人编写了可视化的CNameList类。 最明显的natvis创作:

   <?xml version="1.0" encoding="utf-8"?>
 <AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
   <Type Name="CNameList">
     <Expand>
       <ExpandedItem>m_list</ExpandedItem>
     </Expand>
   </Type>
 
   <Type Name="CName">
     <DisplayString>{m_first} {m_last}</DisplayString>
     <Expand>
       <Item Name="First">m_first</Item>
       <Item Name="Last">m_last</Item>
     </Expand>
   </Type>
 </AutoVisualizer>

会显示如下:

因为我们希望以可视化查看CNameList对象的内容,而不是它的实现细节,我们可以不关心内部向量的大小或容量,也关于每个CNAME对象在列表中的内存地址,或周围的引号姓氏和名字,以表明它们是作为单独的字符串存储。 使用Visual Studio 2012,去掉这混乱是可能的,但比较繁琐,并且需要可视化的CNAME和CNameList被加上了STL的实现细节。 例如,在VS2012我们可以摆脱的尺寸和载体的容量,以及CNAME对象的存储器地址,通过与该更换可视化对于CNameList的:

  <Type Name="CNameList">
     <Expand>
       <IndexListItems>
         <Size>m_list._Mylast - m_list._Myfirst</Size>
         <ValueNode>*m_list._Myfirst[$i]</ValueNode>
       </IndexListItems>
     </Expand>
   </Type>
  <Type Name="CName">
     <DisplayString Condition="m_first._Myres &lt; m_first._BUF_SIZE &amp;&amp; m_last._Myres &lt; m_last._BUF_SIZE">{m_first._Bx._Buf,sb} {m_last._Bx._Buf,sb}</DisplayString>
     <DisplayString Condition="m_first._Myres &gt;= m_first._BUF_SIZE &amp;&amp; m_last._Myres &lt; m_last._BUF_SIZE">{m_first._Bx._Ptr,sb} {m_last._Bx._Buf,sb}</DisplayString>
     <DisplayString Condition="m_first._Myres &lt; m_first._BUF_SIZE &amp;&amp; m_last._Myres &gt;= m_last._BUF_SIZE">{m_first._Bx._Buf,sb} {m_last._Bx._Ptr,sb}</DisplayString>
     <DisplayString Condition="m_first._Myres &gt;= m_first._BUF_SIZE &amp;&amp; m_last._Myres &gt;= m_last._BUF_SIZE">{m_first._Bx._Ptr,sb} {m_last._Bx._Ptr,sb}</DisplayString>
 
     <Expand>
       <Item Condition="m_first._Myres &lt; m_first._BUF_SIZE" Name="First">m_first._Bx._Buf,sb</Item>
       <Item Condition="m_first._Myres &gt;= m_first._BUF_SIZE" Name="First">m_first._Bx._Ptr,sb</Item>
       <Item Condition="m_last._Myres &lt; m_last._BUF_SIZE" Name="Last">m_last._Bx._Buf,sb</Item>
       <Item Condition="m_last._Myres &gt;= m_last._BUF_SIZE" Name="Last">m_last._Bx._Ptr,sb</Item>
     </Expand>
   </Type>

虽然这些可视化的工作肯定的,因为它们产生在监视窗口中所需的输出整洁感。他们需要更多的工作,编写和维护。 首先,可视化工具为CNameList和CNAME现在对类在STL私有成员的依赖。 由于实施细则STL如有更改,这些可视化工具是在Visual Studio中的未来版本中无法正常工作,如果STL实现改变这些条目依赖于一些风险。 此外,如果CNameList的分布有可能被列入任何版本的Visual Studio中的头文件,你可能需要包括CNAME单独natvis条目,对于STL的每个实现,那么必须更新所有的人,任何时间在CNAME的实施改变了未来。

此外,当观察仪的内部类有在它条件句的条件句结束的方式,使可视一团糟相乘。 例如,内置的观察仪的std :: basic_string的有两种可能的显示字符串的情况:

  <Type Name="std::basic_string&lt;char,*&gt;">
     <DisplayString Condition="_Myres &lt; _BUF_SIZE">{_Bx._Buf,s}</DisplayString>
     <DisplayString Condition="_Myres &gt;= _BUF_SIZE">{_Bx._Ptr,s}</DisplayString>
     <StringView Condition="_Myres &lt; _BUF_SIZE">_Bx._Buf,s</StringView>
     <StringView Condition="_Myres &gt;= _BUF_SIZE">_Bx._Ptr,s</StringView>
     <Expand>
         <Item Name="[size]">_Mysize</Item>
         <Item Name="[capacity]">_Myres</Item>
         <ArrayItems>
             <Size>_Mysize</Size>
             <ValuePointer Condition="_Myres &lt; _BUF_SIZE">_Bx._Buf</ValuePointer>
             <ValuePointer Condition="_Myres &gt;= _BUF_SIZE">_Bx._Ptr</ValuePointer>
         </ArrayItems>
     </Expand>
 </Type>

CNameList展台为Visual Studio 2013

在Visual Studio 2013中,可以这样编写整洁的CNameList在监视窗口:

  <?xml version="1.0" encoding="utf-8"?>
 <AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
   <Type Name="CNameList">
     <Expand>
       <ExpandedItem>m_list,view(simple)na</ExpandedItem>
     </Expand>
   </Type>
 
   <Type Name="CName">
     <DisplayString>{m_first,sb} {m_last,sb}</DisplayString>
     <Expand>
       <Item Name="First">m_first,sb</Item>
       <Item Name="Last">m_last,sb</Item>
     </Expand>
   </Type>
 </AutoVisualizer>

多个对象视图

在Visual Studio 2012中,<类型>条目只能描述一种方式来查看的对象。

在Visual Studio 2013年,每种类型仍然只有一个默认的视图,而现在它是可能的natvis项来定义,可以通过适当的格式说明访问其他视图。 例如,在Visual Studio 2013的可视化的std ::矢量这样做是这样的:

  <Type Name="std::vector&lt;*&gt;">
     <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>

在<DisplayString>和<ArrayItems>元素总是使用,而“[大小]”和“[容量]”项目被排除在了有“简单”的名称的视图。 通常情况下,将显示使用默认视图,它会显示所有元素对象。 然而,“,图”格式说明可用于指定备用视图,如图整数的简单向量的本实施例。 需要注意的是“VEC,视图(XXX)”的行为完全一样的默认视图因为载体natvis条目不包含任何特殊行为“XXX”的观点。

如果要被添加到natvis元件,而不是除去从一个特定视图中,可以使用,而不是“ExcludeView”该“IncludeView”属性。 你也可以指定的意见“IncludeView”和“ExcludeView”分号分隔的属性列表,如果你想属性应用到一组的意见,而不是只有一个。 例如,该可视化将显示“备用视图”使用两种“视图(备用)”或“视图(alternate2)”的显示文本,而在其他情况下,“默认视图”。

 <Type Name="MyClass">
     <DisplayString IncludeView="alternate; alternate2">Alternate view </DisplayString>
     <DisplayString>Default View</DisplayString>
   </Type>

所以,回到我们的例子中,我们CNameList以可视化的“载体”可视化定义的“简单”的观点的优势,消除的大小和容量节点杂波:

  <Type Name="CNameList">
     <Expand>
       <ExpandedItem>m_list,view(simple)na</ExpandedItem>
     </Expand>
   </Type>

跳过存储器地址

  <Type Name="CNameList">
     <Expand>
       <IndexListItems>
         <Size>m_list._Mylast - m_list._Myfirst</Size>
         <ValueNode>*m_list._Myfirst[$i]</ValueNode>
       </IndexListItems>
     </Expand>
   </Type>

在我们的CNameList例子中,我们使用“呐”格式说明隐藏CNAME对象,这是不重要的内存地址。 无“,不适用”格式说明,隐藏内存地址将需要复制粘贴,修改为可视化的std ::向量,使其取消引用矢量内的元素,如图所示这里。

还应当指出的是,“娜”格式说明是不太一样的对其操作“*”。 尽管“呐”格式说明会忽略数据的存储地址所指向,仍然会显示有关该地址的任何可用的符号信息。 例如,在功能的情况下,“* wmain”将是一个语法错误,但“wmain,NA”表示“wmain”功能的模块和签名,省略存储器地址。 同样,“&myGlobal,娜”仍显示你的指针指向符号“INT myGlobal”。 在“NA”格式说明,也可以用在内存地址中的一个函数中,如图中的“(void *)以EIP,呐”的例子。 这可以使“呐”格式说明用于可视化已记录对象的内部,用于调试的堆栈跟踪颇具吸引力。

传播格式说明

尽管“SB”格式说明已经存在在Visual Studio 2012,创作的CNAME可视化这样的VS2012不工作:

  <Type Name="CName">
     <DisplayString>{m_first,sb} {m_last,sb}</DisplayString>
     <Expand>
       <Item Name="First">m_first,sb</Item>
       <Item Name="Last">m_last,sb</Item>
     </Expand>
   </Type>

当应用到矢量对象时,Visual Studio 2012将简单地忽略它,就像这样:

在Visual Studio 2013,“X”干脆自动向下传播到向量的孩子,像这样:

其他的可视化改进

使用类的显示字符串中的最后执行的名字:

在Visual Studio 2013,对于一个基类natvis条目可能利用对象的实现类的名称$(类型)宏单元内。 举例来说,如果我们有这个源代码:

class Room
 {
 private:
     int m_squareFeet;
 
 public:
     Room() : m_squareFeet(100) {}
 
     virtual void Print() = 0;
 };
 
 class Bedroom : public Room
 {
 public:
     virtual void Print() { printf("Bedroom");  }
 
 };
 
 class LivingRoom : public Room
 {
 public:
     virtual void Print() { printf("Living room");  }
 
 };
 
 class DiningRoom : public Room
 {
 public:
     virtual void Print() { printf("Dining room");  }
 };
 
 int _tmain(int argc, _TCHAR* argv[])
 {
     Bedroom br;
     LivingRoom lr;
     DiningRoom dr;
 
     br.Print();
     lr.Print();
     dr.Print();
 }

我们可以写一个可视化工具类“室”是这样的:

  <?xml version="1.0" encoding="utf-8"?>
 <AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
   <Type Name="Room">
     <DisplayString>{m_squareFeet}-square foot $(Type)</DisplayString>
   </Type>
 </AutoVisualizer>

这将显示我们有哪种类型的房间,就像这样:

在Visual Studio 2012,取得该显示将需要创建一个单独的<类型>元素为每种类型的房间。

请注意,使用美元(类型)是大小写敏感的。 $(TYPE)将无法正常工作。 此外,使用美元(类型)需要的基类来包含至少一个虚拟函数,因为没有一个V表的存在,调试器没有办法知道对象的实现类实际上是。

支持循环链表

在Visual Studio 2013中,<LinkedListItems>元素增加了圆形表指向回到列表的头部,表示终端的支持。 例如,用下面的源代码:

 class CircularList
 {
 private:
     struct Node
     {
         int m_value;
         Node* m_pNext;
     };
 
     Node* m_pFirst;
 
     Node* GetTail()
     {
         if (!m_pFirst)
             return NULL;
 
         Node* pNode = m_pFirst;
         while (pNode->m_pNext != m_pFirst)
             pNode = pNode->m_pNext;
 
         return pNode;
     }
 public:
     CircularList() : m_pFirst(NULL) {}
 
     ~CircularList()
     {
         Node* pNode = m_pFirst;
         while (pNode != m_pFirst)
         {
             Node* pNext = pNode->m_pNext;
             delete pNode;
 
             pNode = pNext;
         }
     }
 
     void AddTail(int i)
     {
         Node* pNewNode = new Node();
 
         if (m_pFirst)
             GetTail()->m_pNext = pNewNode;
         else
             m_pFirst = pNewNode;
 
         pNewNode->m_value = i;
         pNewNode->m_pNext = m_pFirst;
     }
 };
 
 int _tmain(int argc, _TCHAR* argv[])
 {
     CircularList list;
     list.AddTail(1);
     list.AddTail(2);
     list.AddTail(3);
 
        return 0;
 }

我们可以用一个简单的元素,像这样显示的“名单”的价值:

   <?xml version="1.0" encoding="utf-8"?>
 <AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
   <Type Name="CircularList">
     <Expand>
       <LinkedListItems>
         <HeadPointer>m_pFirst</HeadPointer>
         <NextPointer>m_pNext</NextPointer>
         <ValueNode>m_value</ValueNode>
       </LinkedListItems>
     </Expand>
   </Type>
 </AutoVisualizer>

在Visual Studio 2013,输出是这样的:

在Visual Studio 2012年,名单将被假定为永远持续下去,因为列表节点的“下一个”指针从来都不是NULL,从而产生这样的输出:

写在最后

Visual Studio 2013旨在解决natvis框架缺陷,改进其可视化体验。

使用Visual Studio 2013编写可维护的本地可视化(natvis)的更多相关文章

  1. 【Python】- 如何使用Visual Studio 2013编写python?

    安装Visual Studio 2013 1.VS2013下载安装略 安装python2.7 1.从官网下载python2.7,下载地址:https://www.python.org/getit/  ...

  2. 如何用Visual Studio 2013 (vs2013)编写C语言程序

    如何用Visual Studio 2013 (vs2013)编写C语言程序 (2014-05-16 10:58:15)   Visual Studio 2013是一个很强大的软件,但是刚开始用Visu ...

  3. 让Visual Studio 2013为你自动生成XML反序列化的类

    Visual Sutdio 2013增加了许多新功能,其中很多都直接提高了对代码编辑的便利性.如: 1. 在代码编辑界面的右侧滚动条上显示不同颜色的标签,让开发人员可以对所编辑文档的修改.查找.定位情 ...

  4. [.net 面向对象程序设计深入](3)UML——在Visual Studio 2013/2015中设计UML活动图

    [.net 面向对象程序设计深入](3)UML——在Visual Studio 2013/2015中设计UML活动图 1.活动图简介 定义:是阐明了业务用例实现的工作流程. 业务工作流程说明了业务为向 ...

  5. Visual studio 2013安装

    最头疼装一些需要安装插件的软件,刚开始下载了VS2013的一个版本,安装到一半就发现还得装一些必要插件,然后得重新删了再安装,倒弄了还几次才装好.这是第一次安装时是出现的情况. 第二次尝试安装,把所有 ...

  6. 关闭 Visual Studio 2013 的 Browser Link 功能

    最近公司弄新项目需要用 MVC,就把 IDE 升级到了 Visual Studio 2013,在开发的时候发现有好多请求一个本地49925的端口 . 很奇怪,一开始以为是 Visual Studio ...

  7. Visual Studio 2013 Web开发、新增功能:“Browser Link”

    微软正式发布Visual Studio 2013 RTM版,微软还发布了Visual Studio 2013的最终版本..NET 4.5.1以及Team Foundation Server 2013. ...

  8. Visual Studio 2013新功能

    微软打破了Visual Studio两年升级一次的传统,Visual Studio 2012发布还不足一年,微软就计划发布了Visual Studio 2013了.在今天的TechEd大会上,微软宣布 ...

  9. Visual Studio 2013 Web开发、新增功能:“Browser Link”

    微软正式发布Visual Studio 2013 RTM版,微软还发布了Visual Studio 2013的最终版本..NET 4.5.1以及Team Foundation Server 2013. ...

随机推荐

  1. eclipse Ctrl +左键查看源代码Source not found

    Windows->Preferences->Java->Installed JREs->...(default)->Edit->Program Files\Java ...

  2. python引入导入自定义模块和外部文件

    参考:http://blog.csdn.net/devil_2009/article/details/15816237 项目中想使用以前的代码,或者什么样的需求致使你需要导入外部的包 如果是web 下 ...

  3. 一个基于集成jenkins的测试平台

    (一)先看测试业务的情况: 有各种各样的任务包括代码构建.部署搭建.单元测试.功能自动化测试(包括许多模块的功能自动化测试,有十几个居多),性能测试.正确性验证:复杂一点的是这些任务在不同的测试阶段中 ...

  4. Python多线程学习笔记

    Python中与多线程相关的模块有 thread, threading 和 Queue等,thread 和threading模块允许程序员创建和管理线程.thread模块提供了基本的线程和锁的支持,而 ...

  5. Python Socket,How to Create Socket Cilent? - 网络编程实例

    文章出自:Python socket – network programming tutorial by Silver Moon 原创译文,如有版权问题请联系删除. Network programin ...

  6. SSH搭建完美CURD,含分页算法

    今日开始研究使用java平台上的框架解决web服务端的开发. 这是一个完整的SSH实例,在马士兵老师的SSH整合代码基础上,增加用户的增删改查,同时实现structs方式的分页 放出源代码供大家学习参 ...

  7. linux管道的容量和内部组织方式

    1.管道容量  count=65536,即64KB #include<stdio.h> #include<sys/types.h> #include<unistd.h&g ...

  8. Kinetic使用注意点--canvas

    <virtual> new Canvas(width, height) 参数: width:canvas宽度 height:canvas高度 方法: applyShadow(shape, ...

  9. C语言字符知识狭区

    C语言字符在用户接口软件编程上经常用到,但是有一些狭区会让编程出现一些小BUG,现在总结与此. 1.'\\' 代表的是字符\,而'\'是不能代表字符\的.通常\后面都要跟上数字或者其他字母来表示一个特 ...

  10. Amazon Alexa 语音识别1 : 简介

    Alexa是Amazon自家的语音识别技术,需要配合自家的Echo音箱使用.开发者可以在Amazon上建立自己的程序(Skill)来连接到自己的应用或是硬件.例如,用户家里有一套xx牌的智能灯,现在希 ...