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 修复之 ...
随机推荐
- 2017团体程序设计天梯赛大区赛 L3-3 球队“食物链”
思路: 状压dp. 实现: #include <iostream> #include <cstdio> #include <cstring> using names ...
- [BZOJ1085][SCOI2005]骑士精神 搜索
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1085 大的思路是迭代加深搜索,我们加一个明显的剪枝,当棋盘中位置不对的骑士的数目加上已经走 ...
- R in action读书笔记(10)-第八章:回归-- 异常观测值 改进措施
8.4 异常观测值 8.4.1 离群点 car包也提供了一种离群点的统计检验方法.outlierTest()函数可以求得最大标准化残差绝对值Bonferroni调整后的p值: > library ...
- PHP会话控制考察点
为什么要使用会话控制技术 HTTP协议是无状态的,也就是说HTTP没有一个内建的机制来维护两个事务之间的状态.当一个用户完成一个请求发起第二个请求的时候,服务器无法知道这次请求是来自于上一次的客户.而 ...
- swift 语言评价
杂而不精,一团乱麻!模式乱套,不适合作为一门学习和研究语言. 谢谢 LZ 介绍,看完之后更不想用 Swift 了.从 C++那里抄个 V-Table 来很先进嘛?别跟 C++一样搞什么 STL 就好了 ...
- Axure 9 面板折叠显示隐藏
1 首先放置一个面板1作为点击事件: 2 另外一个面板2或者其他组建,将其设置为动态面板,然后隐藏 3 给面板1添加如下事件,即可: 4 我们点击面板1,可以实现展开隐藏面板2的动态效果
- Domain Adaptation论文笔记
领域自适应问题一般有两个域,一个是源域,一个是目标域,领域自适应可利用来自源域的带标签的数据(源域中有大量带标签的数据)来帮助学习目标域中的网络参数(目标域中很少甚至没有带标签的数据).领域自适应如今 ...
- BZOJ1079: [SCOI2008]着色方案 (记忆化搜索)
题意:有n个木块排成一行,从左到右依次编号为1~n.你有k种颜色的油漆,其中第i种颜色的油漆足够涂ci个木块. 所有油漆刚好足够涂满所有木块,即c1+c2+...+ck=n.相邻两个木块涂相同色显得很 ...
- WebDriver的多浏览器测试的浏览器驱动程序
1.在使用IE浏览器进行WebDriver自动化测试之前,需要从http://docs.seleniumhq.org/download/网站上下载一个WebDriver链接IE浏览器的驱动程序,文件名 ...
- Hadoop架构模型
1.hadoop 1.x架构模型:分布式文件存储系统:HDFSNameNode(主节点:管理元数据) secondaryNameNode(作用是合并元数据信息,辅助NameNode管理元数据信息)Da ...