32

I'm running Visual Studio Enterprise 2015, version 14.0.23107.0 D14REL.

When debugging a C++ program I cannot see the contents of STL containers.

I've got the "Show raw structure of objects in variables windows" option unchecked (Tools->Options->Debugging->General).

Here's an example that illustrates the problem:

#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;
}

In the Locals or Watch windows I see the following:

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

If I then check the "Show raw structure..." option, I can correctly drill down into the vector and string objects, but still not the list!

Is there another option that I've missed, or is this a genuine bug in VS?

Graham
  • 371
  • 1
  • 4
  • 12
  • 2
    MSFT support for viewing C++ data structures in the debugger has not always been stellar over the years. Wouldn't surprise me if this was overlooked. – edtheprogrammerguy Sep 18 '15 at 15:54
  • 5
    Did you compile debug build or you try to debug in release? – Melkon Sep 18 '15 at 15:56
  • This normally works in VS2015. If you're compiling a Release build the debugger may not be able to resolve all your variables. The other (unlikely) possibility I can think of is a corrupt [natvis file](https://msdn.microsoft.com/en-us/library/jj620914.aspx) – mattnewport Sep 18 '15 at 17:19
  • Sorry, I should have said it's a debug build. – Graham Sep 18 '15 at 19:37
  • 3
    I had the same issue. I managed to get 'Natvis' working by following few steps at the top of the link - https://msdn.microsoft.com/en-us/library/jj620914.aspx - first note "You cannot use the Natvis framework for visualizations when". I unchecked all of those and it works now. – Edgars Oct 28 '15 at 08:38
  • 1
    Thanks Edgars, that link has the fix! In my case, I only unchecked "Use Native Compatibility Mode" and it now works fine :) I'm pretty sure I never checked this in the first place, so it looks like MS screwed up the default setting ;) (You should submit this as an answer BTW!) – Graham Oct 28 '15 at 13:22
  • VS2015 Update 2 is now released, [see this page](https://www.visualstudio.com/en-us/news/vs2015-update2-vs.aspx). – Chris O Mar 30 '16 at 19:12

7 Answers7

27

I had a same problem.

You need to go into Tools->Options->Debugging->General and uncheck both "Use Managed Compability Mode" and "Use Native Compability Mode".

  • 1
    Wow, thanks a lot - saved my day. Seems this changed between VS 2013 and VS 2015 versions (looks like setting doesn't exist in VS 2013). For what it's worth: Before, I also couldn't debug into a DLL I am developing, but now (after disabling native compatibility mode) I can do that again. – volzotan Aug 30 '16 at 10:02
  • That's strange; I've the latest version `14.0.25431.01 Update 3` and I must check these checkboxes in order to re-enable this feature. – Skywalker13 Oct 25 '16 at 10:30
6

I have the same problem, but only if Debugger Type is "Mixed" (or if my project contains C++/CLI code and the type is "Auto"). With Debugger Type "Native Only", both std::vector as a whole and its single element are shown correctly.

You can use Debugger Type "Native Only" for debugging pure C/C++ portion of a mixed project, you just can't step into C++/CLI code.

Addition: if you have a problem with viewing in the native debugger, you might want to read this: https://msdn.microsoft.com/en-us/library/jj620914.aspx

Eugene
  • 6,194
  • 1
  • 20
  • 31
  • Thanks for the suggestion Eugene, but changing the Debugger Type doesn't help :( I changed from Auto to Native Only, rebuilt the test project, even restarted Visual Studio, but no difference. – Graham Oct 22 '15 at 07:19
  • There's some additional information in this answer from what looks to be a Microsoft employee. They also suggested this same work around, but have some additional suggestions as well : https://connect.microsoft.com/VisualStudio/feedback/details/1735111/debugger-completely-broken-when-using-std-boost-types-in-c – premes Feb 23 '16 at 01:45
2

"Works on my box"... finally... at long last... but specifically had to do these steps:

  1. Install VS2015 Update 2, takes about three hours
  2. Uncheck both "Use Managed Compatibility Mode" and "Use Native Compatibility Mode" options from Tools | Options | Debugging
  3. Add this reg switch, as indicated in "How to Try It Out" :

Reg key: HKCU\Software\Microsoft\VisualStudio\14.0_Config\AD7Metrics\ExpressionEvaluator\{3A12D0B7-C26C-11D0-B442-00A0244A1DD2}\{994B45C4-E6E9-11D2-903F-00C04FA302A1} Add DWORD LoadInShimManagedEE set to 0

Now I can view Standard containers like I've never done before like I used to do in earlier versions. Most of our native C++ code gets called from C++/CLI code so this fix is quite necessary.

Chris O
  • 5,017
  • 3
  • 35
  • 42
  • 2
    Excellent, and you no longer need to edit the registry because they've packaged it up as a [vsix](https://visualstudiogallery.msdn.microsoft.com/ab846c83-56be-41b4-88e7-95895ab528dc) (still need to install the KB first, as explained at the link). And they promise both of the above will be included in update 3. – dlf May 10 '16 at 21:02
1

No, This is not a bug in Visual Studio!

Microsoft Visual Studio 2005 was the first of the Visual Studio versions to support debugger visualizers usable for template classes.

You are actually lacking a visualizer for your std::<list>

Add a formatting rule in autoexp.dat file.

You can find the file here

%VSINSTALLDIR%\Common7\Packages\Debugger\autoexp.dat

Append a new rule to the [Visualizer] section.

e.g. To view the list size

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

We are accessing the _Mysize member of the std::<list> implementation. _Mysize gives you the number of elements in the list.

Pattern Matching:

std::list<*,*> will match std::list<int> and std::list<int,std::allocator<int> >

std::list<*,*> will match std::list<string> and std::list<string,std::allocator<string> >

To view children items

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

or even

std::list<*,*>{
  children
  (
    #list(size: $c._Mysize,
          head: $c._Myhead->_Next,
          next: _Next
    ) : $e._Myval
  )
}
user1
  • 4,031
  • 8
  • 37
  • 66
  • 1
    Thanks user1. But the thing is, every Visual Studio (for a few versions now) has come with out-of-the-box support for visualizing STL containers. I've just confirmed with both 2010 and 2013, I don't need to mess around with the visualizers! And the autoexp.dat file for VS 2015 already includes the STL containers, they just don't seem to have any effect. – Graham Sep 19 '15 at 09:06
  • Please check "Show Raw Structure...." Option once again, if it is turned on then all customisations are disabled – user1 Sep 19 '15 at 09:33
  • 1
    The "Show raw structure..." option is definitely unchecked. If I check it, then I do indeed get the raw structure, so that bit is working just fine. Uncheck it again, and I get the errors described in the original post. – Graham Sep 19 '15 at 10:13
  • Okay, now compare std::list visualizer in my solution above with one from autoexp.dat, Any differences? – user1 Sep 19 '15 at 10:19
  • Interestingly, the autoexp.dat file is identical in VS 2012, 2013, and 2015. There's definitely a bug in VS 2015! Or MS changed something for 2015 but didn't update autoexp.dat ;) I deleted the existing std::list rules and tried your size rule; it doesn't show the size, but does show the raw structure instead! Thanks for your help user1, but don't worry anymore about this, it's an annoyance but something I can live with until MS produce a fix. – Graham Sep 19 '15 at 10:46
  • Thank you Graham Bull!! I went through 30 suggestions before I found 'show raw structure'. The option makes it sound like it's an add-on, but really, it does just suppress the visualizers – zeromus Feb 12 '19 at 00:06
0

For VS2015, I had to modify autoexp.dat for list as such:

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
    )
}    

These changes came from inspecting the VS2015 stl.natvis and noting the changes that were made to various data structures marked with <!-- VC 2015 -->

I've made appropriate changes to other stl structures as well, although be warned I have not tested them all

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
    )
}
0

Had the same trouble. My environment: Win 10 prof. x64, VS 2015, update 3, toolset v140, c++ project. I even could not see strings in addition. The problem seems to been introcuded either by an update or an extension.

Solution: I made a fresh installation of VS2015 on another system (win 7 prof. x64). This was installed with update 3 (net. install). On this machine all worked fine: could see strings (without expanding the dbg tooltip). For containers the size is shown on move over and you can inspect elements. Perfect.

What is the difference ? I don't know. I compared the .natvis files on both machines and the C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\Packages\Debugger\autoexp.dat

No differences.

So the solution was quite usual in such cases: Uninstall VS2015. Run a reg cleaner. Reinstall. Start. My old settings were present from first start and the debug inspection worked again. Problem solved.

nullptr
  • 93
  • 11
0

I am running VS2015 SP3. I spent 2 hours trying every fix the internet told me to do. Nothing worked! My last resort was reinstalling VS (which takes hours.) So I went to "Add/Remove Programs" > "Microsoft Visual Studio Professional 2015". However, instead of uninstalling, I tried doing a "Repair". I don't know what caused the problem, but repairing the install fixed it.

Jeff Lamb
  • 5,755
  • 4
  • 37
  • 54