• 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.0XmlSchemas1033 atvis.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&lt;*&gt;" 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&lt;*&gt;">
        <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个元素。

      

      

  • 相关阅读:
    Shell编程-05-Shell中条件测试与比较
    Shell编程-04-Shell中变量数值计算
    Shell编程-03-Shell中的特殊变量和扩展变量
    Shell编程-02-Shell变量
    Shell编程-01-Shell脚本初步入门
    Windows与Linux相互远程桌面连接
    awk基础05-自定义函数和脚本
    使用Kafka Connect创建测试数据生成器
    设置KAFKA
    Apache Kafka使用默认配置执行一些负载测试来完成性能测试和基准测试
  • 原文地址:https://www.cnblogs.com/hujichen/p/5997310.html
Copyright © 2020-2023  润新知