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 修复之 ...
随机推荐
- 转】R利剑NoSQL系列文章 之 Cassandra
原博文出自于: http://blog.fens.me/category/%E6%95%B0%E6%8D%AE%E5%BA%93/page/3/ 感谢! R利剑NoSQL系列文章 之 Cassandr ...
- R Programming week1-Data Type
Objects R has five basic or “atomic” classes of objects: character numeric (real numbers) integer co ...
- 洛谷 P1886 滑动窗口 (数据与其他网站不同。。)
题目描述 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口.现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值. 例如: The array i ...
- mac webstrom 安装less
1.检验电脑是否安装less lessc -v 2.如果没有执行全局安装命令 npm install -g less 3.webstrom -> Preferencs-> File Wat ...
- Android(java)学习笔记188:学生信息管理系统案例(SQLite + ListView)
1.首先说明一个知识点,通常我们显示布局文件xml都是如下: setContentView(R.layout.activity_main): 其实每一个xml布局文件就好像一个气球,我们可以使用Vie ...
- JavaSE-14 异常处理
学习要点 使用try-catch-finally处理异常 使用throw.throws抛出异常 异常及其分类 log4j记录日志 异常 1 异常的定义 异常是指在程序的运行过程中所发生的不正常的事件 ...
- iOS工具】rvm、Ruby环境和CocoaPods安装使用及相关报错问题解决
〇.前言 <p>在iOS开发中 CocoaPods作为库依赖管理工具就是一把利器. 有了 CocoaPods则无需再通过拖 第三方库及第三方库所依赖的 framework静态库到项目中等麻 ...
- GNU编译器学习 --> 如何链接外部库【Linking with external libraries】
库也就是我们常说的library,一个库是若干个已经编译过的目标文件(.obj)的集合,它可以被链接到程序里.那么我们最常见的使用就是,我们在编程时会调用一些函数,这些函数别人已经写好了,它就放在库里 ...
- jenkins构建项目记录1
jenkins安装见上篇随笔 1.新建任务 2.构建一个自由风格的软件项目 3.源码管理设置 4.构建环境 5.构建 6.构建后操作
- KBE_创建项目和基本常识
此笔记参考官方文档 第一个项目 资产库:是每一个项目文件夹的名称,使用KBE提供的生成工具生成一个最小资产库,其中包含了很多常用的工具,默认名server_assets: res:放置一些资源(入地图 ...