在Visual Studio 2015中检查STL容器

Inspecting STL containers in Visual Studio 2015

本文关键字:检查 STL 容器 2015 Visual Studio      更新时间:2023-10-16

我运行的是Visual Studio Enterprise 2015, version 14.0.23107.0 D14REL.

调试c++程序时,我看不到STL容器的内容。

我已经得到了"显示变量窗口中对象的原始结构"选项未选中(工具->选项->调试->常规)。

这里有一个例子来说明这个问题:

#include <list>
#include <string>
#include <vector>
int main()
{
    std::string string = "test";
    std::vector<int> vector{ 4, 5, 6 };
    std::list<std::string> list{ "one", "two", "three" };
    return 0;
}

在Locals或Watch窗口中,我看到以下内容:

list         [...]()
vector       [...](...
  (error)    0
  (error)    0
string       {npos=4294967295}
  (error)    0
  (error)    0

如果我检查"显示原始结构…"选项,我可以正确地钻到向量和字符串对象,但仍然不是列表!

是否有另一个选项我错过了,或者这是一个真正的错误在VS?

我也遇到过同样的问题。

您需要进入Tools->Options->Debugging->General并取消勾选"使用托管兼容性模式"answers"使用本机兼容性模式"。

我有同样的问题,但只有当调试器类型是"混合"(或者如果我的项目包含c++/CLI代码和类型是"自动")。当调试器类型为"Native Only"时,std::vector作为一个整体和它的单个元素都能正确显示。

你可以使用调试器类型"Native Only"来调试纯C/c++混合项目的部分,你只是不能进入c++/CLI代码。

补充:如果您在本机调试器中查看时遇到问题,您可能需要阅读以下内容:https://msdn.microsoft.com/en-us/library/jj620914.aspx

"Works on my box"…最后……终于……但是必须执行以下步骤:

  1. 安装VS2015更新2,大约需要三个小时
  2. 取消"使用托管兼容模式"answers"使用本机兼容模式"选项从工具|选项|调试
  3. 添加这个reg开关,如"如何尝试"所示:

Reg关键:HKCUSoftwareMicrosoftVisualStudio14.0_ConfigAD7MetricsExpressionEvaluator{3A12D0B7-C26C-11D0-B442-00A0244A1DD2}{994B45C4-E6E9-11D2-903F-00C04FA302A1}添加DWORD LoadInShimManagedEE set到0

现在我可以查看标准容器,这是我以前从未做过的,就像我以前在早期版本中所做的那样。我们的大多数本地c++代码都是从c++/CLI代码中调用的,所以这个修复是非常必要的。

不,这不是Visual Studio中的bug !

Microsoft Visual Studio 2005是第一个支持可用于模板类的调试器可视化器的Visual Studio版本。

您实际上缺少std::<list>的可视化工具

autoexp.dat文件中添加格式化规则。

你可以在这里找到文件

%VSINSTALLDIR%Common7PackagesDebuggerautoexp.dat

[Visualizer]部分添加一个新规则

。查看列表大小

std::list<*,*>{
  preview
    (
      #("[list size=", $e._Mysize, "]")
    )
}

我们正在访问std::<list>_Mysize成员。_Mysize给出列表中元素的个数。

模式匹配:

std::list<*,*>将匹配std::list<int>std::list<int,std::allocator<int> >

std::list<*,*>将匹配std::list<string>std::list<string,std::allocator<string> >

查看子项目

std::list<*,*>{
  children
  (
    #(
      first item: $e._Myhead->_Next->_Myval,
      second item: $e._Myhead->_Next->_Next->_Myval,
      [third item]: $e._Myhead->_Next->_Next->_Next->_Myval
    )
  )
}

或者

std::list<*,*>{
  children
  (
    #list(size: $c._Mysize,
          head: $c._Myhead->_Next,
          next: _Next
    ) : $e._Myval
  )
}

对于VS2015,我必须修改autoexp.dat为列表如下:

std::list<*>{
    preview (
        #(
            "[",
            $e._Mypair._Myval2._Mysize,
            "](",
        #list(
            head: $e._Mypair._Myval2._Myhead->_Next,
            size: $e._Mypair._Myval2._Mysize,
            next: _Next
        ) : $e._Myval,
            ")"
        )
    )  
    children (
        #list(
            head: $e._Mypair._Myval2._Myhead->_Next,
            size: $e._Mypair._Myval2._Mysize,
            next: _Next
        ) : $e._Myval
    )
}    

这些变化来自于对VS2015版本的检查。并注意对标记为<!-- VC 2015 -->

的各种数据结构所做的更改。

我也对其他的stl结构做了适当的修改,尽管需要注意的是,我还没有对它们全部进行测试

std::unique_ptr<*>{
    preview (
        #if ($e._Mypair._Myval2 == 0) (
            "empty"
        ) #else (
            #(
                "unique_ptr ",
                *$e._Mypair._Myval2
             )
        )
    )
    children (
        #if ($e._Mypair._Myval2 == 0) (
            #array(expr: 0, size: 0)
        ) #else (
            #([ptr] : $e._Mypair._Myval2)
        )
    )
}
std::_Bind<*>{
    preview (
        #(
            "bind(", $e._Mypair,
            ", ", $e._Mypair._Myval2,
            ")"
        )
    )
children (
        #(
            #([f] : $e._Mypair),
            #([bound_args] : $e._Mypair._Myval2)
            )
    )
}
std::_Mem_fn_wrap<*>{
    preview (
        ; We preview the functor returned by mem_fn() with "mem_fn(<stored member function pointer>)".
        #(
            "mem_fn(",
            $e._Pm,
            ")"
        )
    )
    children (
        ; Member function pointers have no children.
        #array(expr: 0, size: 0)
    )
}
std::_Func_impl<*>{
    preview ( $e._Mypair._Myval2 )
    children (
        #(
            #([functor] : $e._Mypair._Myval2),
            #([allocator] : $e._Mypair)
        )
    )
}
std::function<*>{
    preview (
        #if ($e._Mystorage._Ptrs[$e._Impl] == 0) (
            ; Detecting empty functions is trivial.
            "empty"
        ) #else (
            *$e._Mystorage._Ptrs[$e._Impl]
        )
    )
    children (
        #if ($e._Mystorage._Ptrs[$e._Impl] == 0) (
            ; We make empty functions appear to have no children.
            #array(expr: 0, size: 0)
        ) #else (
            #([functor and allocator] : *$e._Mystorage._ptrs[$e._Impl])
        )
    )
}
std::basic_string<char,*>{
    preview     ( #if (($e._Mypair._Myval2._Myres) < ($e._Mypair._Myval2._BUF_SIZE)) ( [$e._Mypair._Myval2._Bx._Buf,s] ) #else ( [$e._Mypair._Myval2._Bx._Ptr,s] ))
    stringview  ( #if (($e._Mypair._Myval2._Myres) < ($e._Mypair._Myval2._BUF_SIZE)) ( [$e._Mypair._Myval2._Bx._Buf,sb] ) #else ( [$e._Mypair._Myval2._Bx._Ptr,sb] ))
    children (
        #(
            #([size] : $e._Mypair._Myval2._Mysize),
            #([capacity] : $e._Mypair._Myval2._Myres),
            #if (($e._Mypair._Myval2._Myres) < ($e._Mypair._Myval2._BUF_SIZE)) (
                #array(expr: $e._Mypair._Myval2._Bx._Buf[$i], size: $e._Mypair._Myval2._Mysize)
            ) #else (
                #array(expr: $e._Mypair._Myval2._Bx._Ptr[$i], size: $e._Mypair._Myval2._Mysize)
            )
        )
    )
}
std::basic_string<unsigned short,*>|std::basic_string<wchar_t,*>{
    preview     ( #if (($e._Mypair._Myval2._Myres) < ($e._Mypair._Myval2._BUF_SIZE)) ( [$e._Mypair._Myval2._Bx._Buf,su] ) #else ( [$e._Mypair._Myval2._Bx._Ptr,su] ))
    stringview  ( #if (($e._Mypair._Myval2._Myres) < ($e._Mypair._Myval2._BUF_SIZE)) ( [$e._Mypair._Myval2._Bx._Buf,sub] ) #else ( [$e._Mypair._Myval2._Bx._Ptr,sub] ))
    children (
        #(
            #([size] : $e._Mypair._Myval2._Mysize),
            #([capacity] : $e._Mypair._Myval2._Myres),
            #if (($e._Mypair._Myval2._Myres) < ($e._Mypair._Myval2._BUF_SIZE)) (
                #array(expr: $e._Mypair._Myval2._Bx._Buf[$i], size: $e._Mypair._Myval2._Mysize)
            ) #else (
                #array(expr: $e._Mypair._Myval2._Bx._Ptr[$i], size: $e._Mypair._Myval2._Mysize)
            )
        )
    )
}
std::deque<*>{
    preview (
            #(
            "[",
            $e._Mypair._Myval2._Mysize,
            "](",
            #array(
                expr: $e._Mypair._Myval2._Map[(($i + $e._Mypair._Myval2._Myoff) / $e._EEN_DS) % $e._Mypair._Myval2._Mapsize][($i + $e._Mypair._Myval2._Myoff) % $e._EEN_DS],
                size: $e._Mypair._Myval2._Mysize
            ),
            ")"
        )
    )
    children (
        #(
            #array(
                expr: $e._Mypair._Myval2._Map[(($i + $e._Mypair._Myval2._Myoff) / $e._EEN_DS) % $e._Mypair._Myval2._Mapsize][($i + $e._Mypair._Myval2._Myoff) % $e._EEN_DS],
                size: $e._Mypair._Myval2._Mysize
            )
        )
    )
}
std::forward_list<*>{
    preview (
        #(
            "(",
            #list(
                head: $e._Mypair._Myval2._Myhead,
                next: _Next
            ) : $e._Myval,
            ")"
        )
    )
    children (
        #list(
            head: $e._Mypair._Myval2._Myhead,
            next: _Next
        ) : $e._Myval
    )
}
std::vector<bool,*>{
    preview (
        #(
            "[",
            $e._Mysize,
            "](",
            #array(
                expr: (bool)(($e._Myvec._Mypair._Myval2._Myfirst[$i / $e._EEN_VBITS] >> ($i % $e._EEN_VBITS)) & 1),
                size: $e._Mysize
            ),
            ")"
        )
    )
    children (
        #(
            #([size] : $e._Mysize),
            #([capacity] : ($e._Myvec._Mypair._Myval2._Myend - $e._Myvec._Mypair._Myval2._Myfirst) * $e._EEN_VBITS),
            #array(
                expr: (bool)(($e._Myvec._Mypair._Myval2._Myfirst[$i / $e._EEN_VBITS] >> ($i % $e._EEN_VBITS)) & 1),
                size: $e._Mysize
            )
        )
    )
}
std::vector<*>{
    preview (
        #(
            "[",
                $e._Mypair._Myval2._Mylast - $e._Mypair._Myval2._Myfirst,
            "](",
            #array(
                expr: $e._Mypair._Myval2._Myfirst[$i],
                size: $e._Mypair._Myval2._Mylast - $e._Mypair._Myval2._Myfirst
            ),
            ")"
        )
    )
    children (
        #(
            #([size] : $e._Mypair._Myval2._Mylast - $e._Mypair._Myval2._Myfirst),
            #([capacity] : $e._Mypair._Myval2._Myend - $e._Mypair._Myval2._Myfirst),
            #array(
                expr: $e._Mypair._Myval2._Myfirst[$i],
                size: $e._Mypair._Myval2._Mylast - $e._Mypair._Myval2._Myfirst
            )
        )
    )
}
std::map<*>|std::multimap<*>|std::set<*>|std::multiset<*>{
    preview (
        #(
            "[",
            $e._Mypair._Myval2._Myval2._Mysize,
            "](",
            #tree(
                head: $e._Mypair._Myval2._Myval2._Myhead->_Parent,
                skip: $e._Mypair._Myval2._Myval2._Myhead,
                left: _Left,
                right: _Right,
                size: $e._Mypair._Myval2._Myval2._Mysize
            ) : $e._Myval,
            ")"
        )
    )
    children (
        #(
            #tree(
                head: $e._Mypair._Myval2._Myval2._Myhead->_Parent,
                skip: $e._Mypair._Myval2._Myval2._Myhead,
                left: _Left,
                right: _Right,
                size: $e._Mypair._Myval2._Myval2._Mysize
            ) : $e._Myval
        )
    )
}
std::unordered_map<*>|std::unordered_multimap<*>|std::unordered_set<*>|std::unordered_multiset<*>|stdext::hash_map<*>|stdext::hash_multimap<*>|stdext::hash_set<*>|stdext::hash_multiset<*>{
    preview (
        #(
            "[",
            $e._List._Mysize,
            "](",
            #list(
                head: $e._List._Myhead->_Next,
                size: $e._List._Mysize,
                next: _Next
            ) : $e._Myval,
            ")"
        )
    )
    children (
        #list(
            head: $e._List._Myhead->_Next,
            size: $e._List._Mysize,
            next: _Next
            ) : $e._Myval
    )
}

也遇到过同样的麻烦。我的环境:Win 10 prof. x64, VS 2015, update 3, toolset v140, c++项目。我甚至看不到另外的弦。这个问题似乎是由更新或扩展引入的。

解决方案:我在另一个系统(win 7教授x64)上重新安装了VS2015。这个已经安装好了随着更新3 (net)。安装)。在这台机器上一切正常:可以看到字符串(不需要展开dbg工具提示)。容器的大小在移动时显示,你可以检查元素。完美。

有什么区别?我不知道。我比较了两者的.natvis文件机器和C:Program Files (x86)Microsoft Visual Studio 14.0Common7PackagesDebuggerautoexp.dat

没有差异。

所以在这种情况下解决方案是很常见的:卸载VS2015。运行一个注册表清理程序。重新安装。开始。我的旧设置从第一次启动和调试检查开始就存在再次工作。问题解决了。

我正在运行VS2015 SP3。我花了两个小时尝试互联网告诉我的每一个修复方法。没有工作!我最后的办法是重新安装VS(这需要几个小时)。所以我去了"添加/删除程序">"Microsoft Visual Studio Professional 2015"。然而,而不是卸载,我试图做一个"修复"。我不知道是什么原因导致的问题,但修复安装解决了它。