VS调试STL问题总结
---恢复内容开始---
以前写代码总觉用自己写的东西比较牛逼,vector?stack?为什么不自己实现。后来才认识到这是个幼稚的想法!首先每次都自己实现是一种重复劳动;其次,自己写的话很难保证没有bug;效率往往也不如STL。STL的优势不在此赘述,最近使用STL的时候发现调试时,监视器中的内容不忍直视,乱七八糟的,经过一番了解才慢慢发现问题所在。在这里总结一下,也希望能帮到遇到同样问题的同学。
首先贴出来,我用的vs2015社区版 update3 调试代码时遇到的问题。item_vec的声明如下:
vector<string> item_vec;
当我想查看一下item_vec中的内容时,watch中的内容如下:

看到这个,我的内心基本是崩溃的,这还看个毛线啊。回过头来想想,为什么vs显示的是这些“乱七八糟”的东西?因为这些正是vector对象的成员。想想一下,vs在提供调试的时候,我们查看一对象a,vs就应该给我显示对象a的成员和值,那我想查看vector的内容时,vs就应该像上面这样显示,没有问题。但是回想以前使用stl,调试时显示的好像不是这种东西,问题出在哪里?
一番查找之后,了解到这个属于vs可视化调试的内容。可视化调试大概就是区别于gdb,提供可视化调试界面的功能。强大的vs在想,我怎么为STL提供给友好的可视界面,那我为STL单独设置一种显示行不行,vector对象显示size, capacity, vector中的所有元素列表等等。这样这个问题貌似就解决了!!!
然而这个问题并没有这么简单,这样做只能解决STL的显示问题,如果用户自己实现了STL功能,或者自己使用了更适合自己的第三方类库,这个时候STL类的定义都完全不一样了,vs就没有办法显示了。推而广之,如果任意一个用户定义的类,而且这个类和STL中的类一样复杂,并且调试的时候经常需要查看这个类的对象的状态,这个时候vs就无法满足要求的。仔细一想这个问题就不能用上面的方案解决。所以微软提供了更牛叉的解决方案:用户自定义显示。
大概的想法是这样的,“我定义的类我做主”,vs提供一种工具,让你自己来决定怎么在调试的时候显示这个类的对象。具体可以访问:https://msdn.microsoft.com/zh-cn/library/jj620914.aspx。简而言之就是,你可以使用一种.natvis的文件来定义一个类的对象在调试时的显示。大概的定义方式如下:
<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>
这个是微软给出的样例,在vs2013中用来定义vector的显示形式,大概的效果如下:

厉害了我的哥,这个就舒服很多嘛!参考微软官方的指南,你就可以为自己的类定义你想要的显示形式。这样就在调试代码的时候就不用加一些为了查看某些值而写一些额外的代码了。
vs在安装时,STL中的类都有默认的显示方案,大概就是上面这张图中的效果。
上面讲的是vs自定义类显示的原理,那为什么我的vs还会有显示问题,不是有默认的显示吗?其实这是vs 社区版update3的一个bug,参考这个链接:https://connect.microsoft.com/VisualStudio/feedback/details/1676171/change-in-c-stl-container-implementation-causes-debug-visualizer-error。bug产生的原因如下:.natvis文件时XML文件,所以正常是需要加上验证的,这个验证文件在C:\Program Files (x86)\Microsoft Visual Studio 14.0\Xml\Schemas\1033\natvis.xsd。但是vs2015社区版update3的这个文件不知道为什么使用的是vs2015RTM版本的xsd文件。导致,vs默认的stl.natvis文件中的一些定义不无通过验证,相应的内容就无法生效,在vs看来相应的内容就只能用raw_data的形式显示。这个问题会在下个版本中解决,目前只能等。上面的连接中有人提到了一种解决的偏方,有兴趣的同学可以尝试一下,我的vs下没有偏方中描述的文件,所以没办法用。
最后再说一说遇到这种现实问题应该怎么去确认问题的原因,如果下次vs再有这种bug,你也可以自己尝试去确认bug的原因。
在vs中可以设置以原始数据的形式查看。“工具”->“选项”->“调试”->“常规”下可以设置“在变量窗口中显示对象的原始数据”,如果希望.natvis生效,需要把这一项取消。
在查看STL(以vector为例)对象时,可以查看output窗口,如果.natvis文件解析异常,会报错。在修改了.natvis文件后可以在watch窗口中执行.natvisreload命令重新加在.natvis文件。
也可以为项目添加.natvis文件,该.natvis文件只会在该项目中生效,并且,修改该.natvis文件会立即生效。参考https://www.zhihu.com/question/41286979。
关于stl.natvis文件,如果需要修改stl.natvis,请注意vs使用的stl版本,不同版本stl对容器元素的声明会不一样,如通用的vector显示:
vs2013:
<Type Name="std::vector<*>" Priority="MediumLow">
<DisplayString>{{ size={_Mylast - _Myfirst} }}</DisplayString>
<Expand>
<Item Name="[capacity]" ExcludeView="simple">_Myend - _Myfirst</Item>
<ArrayItems>
<Size>_Mylast - _Myfirst</Size>
<ValuePointer>_Myfirst</ValuePointer>
</ArrayItems>
</Expand>
</Type>
vs2015:
<Type Name="std::vector<*>">
<DisplayString>{{ size={_Mypair._Myval2._Mylast - _Mypair._Myval2._Myfirst} }}</DisplayString>
<Expand>
<Item Name="[capacity]" ExcludeView="simple">_Mypair._Myval2._Myend - _Mypair._Myval2._Myfirst</Item>
<Item Name="[allocator]" ExcludeView="simple">_Mypair</Item>
<ArrayItems>
<Size>_Mypair._Myval2._Mylast - _Mypair._Myval2._Myfirst</Size>
<ValuePointer>_Mypair._Myval2._Myfirst</ValuePointer>
</ArrayItems>
</Expand>
</Type>
最后的最后,如果是想vs2015社区版update3这样的bug,暂时无法修复时。在watch窗口item_vec[0]会失败,可以使用"&(item_vec.operator[](0)),n",这个表达式可以查看vector中n个元素。
VS调试STL问题总结的更多相关文章
- 使用GDB调试STL容器
GDB中print方法并不能直接打印STL容器中保存的变量,想知道STL容器保存的变量,使用如下办法: 1. 创建文件~/.gdbinit: # # STL GDB evaluators/views/ ...
- gdb调试的艺术——Debug技巧
调试的艺术——Debug技巧总结 (本文从写好的wiki里粘出来的,格式稍乱不影响阅读) 用Q+编号代表问题,A+编号代表答案.用这种方式组织.如无特别说明,这些技巧都是针对Visual Studio ...
- Centos7升级gcc学习笔记
概述 最近在学习<深入应用C++11-代码与优化与工程级应用>,我的gcc版本是gcc-4.8.5是支持C++11的,但是我在作者的github上看了一些C++例子,其中有些是C++14的 ...
- C\C++代码优化的27个建议
1. 记住阿姆达尔定律: funccost是函数func运行时间百分比,funcspeedup是你优化函数的运行的系数. 所以,如果你优化了函数TriangleIntersect执行40%的运行时间, ...
- 【转】C\C++代码优化的27个建议
1. 记住阿姆达尔定律: funccost是函数func运行时间百分比,funcspeedup是你优化函数的运行的系数. 所以,如果你优化了函数TriangleIntersect执行40%的运行时间, ...
- VS Code 配置 C/C++ 环境(转)
写作原因 微软的 VSCode 一直以来为人诟病的一个问题就是对于 C/C++ 工程的编译以及调试支持度有限,配置起来比较复杂,但是 vscode-cpptools 团队经过一段时间的 bug 修 ...
- Centos7升级gcc学习笔记 gcc 4.8.5 -> gcc 5.4.0
摘自:https://www.cnblogs.com/highway-9/p/5628852.html 一.安装开发必备环境: yum groupinstall "Development T ...
- 【转自牛客网】C++类职位校招
作者:./a.out链接:https://www.nowcoder.com/discuss/14022来源:牛客网 话说在牛客网上混迹了半年,也没啥拿的出手的贡献.现在基本上自己的校招生涯要告一段落, ...
- VS Code 配置 C/C++ 环境
写作原因 微软的 VSCode 一直以来为人诟病的一个问题就是对于 C/C++ 工程的编译以及调试支持度有限,配置起来比较复杂,但是 vscode-cpptools 团队经过一段时间的 bug 修复之 ...
随机推荐
- Spirng MVC +Velocity 表单绑定命令对象
通常,表单中的数据在提交之后可以通过Spring MVC的@RequestParam注解在控制器函数的参数列表中中提取出来,但是一旦表单数据过多的话,参数列表将会变得非常长,最好的解决方案是将表单中的 ...
- 前端组件化(二):优化 DOM 操作
看看上一节我们的代码,仔细留意一下 changeLikeText 函数,这个函数包含了 DOM 操作,现在看起来比较简单,那是因为现在只有 isLiked 一个状态.由于数据状态改变会导致需要我们去更 ...
- React.js 简介
React.js 是一个帮助你构建页面 UI 的库.如果你熟悉 MVC 概念的话,那么 React 的组件就相当于 MVC 里面的 View.如果你不熟悉也没关系,你可以简单地理解为,React.js ...
- 微信小程序开发初次尝试-----实验应用制作(一)
初次尝试微信小程序开发,在此写下步骤以做记录和分享. 1.在网上找了很多资料,发现这位知乎大神提供的资料非常全面. 链接 https://www.zhihu.com/question/50907897 ...
- mysql 的 case when then 用法 和null 的判断
表:一个表 aa 有两个字段 id 和 sex ,第1条记录的sex 为空串 ('') 第二条记录的sex 为空 (null) 1. 用法: 第一种: select (case 字段名 whe ...
- Spark学习笔记--Spark在Windows下的环境搭建(转)
本文主要是讲解Spark在Windows环境是如何搭建的 一.JDK的安装 1.1 下载JDK 首先需要安装JDK,并且将环境变量配置好,如果已经安装了的老司机可以忽略.JDK(全称是JavaTM P ...
- matlab遗传算法工具箱
转自http://blog.sina.com.cn/s/blog_5ebcc0240101pnrj.html matlab遗传算法工具箱函数及实例讲解 (2014-01-10 13:03:57) ...
- 大写URL转小写
添加LowercaseRoutesMVC.dll引用.通过“管理—NuGet程序包”搜索LowercaseRoutesMVC,然后点击安装.安装成功后会自动引用LowercaseRoutesMVC.d ...
- Winsock2_WSADATA
使用Winsock2进行win下网络编程的第一步是初始化Winsock.其中需要创建一个WSADATA类型的变量,这个变量用来保存Windows socket的实现信息. typedef struct ...
- GET方法与POST方法的区别
区别一:get重点在从服务器上获取资源,post重点在向服务器发送数据: 区别二:get传输数据是通过URL请求,以field(字段)= value的形式,置于URL后,并用"?" ...