My Favorite Visual Studio Debugger Tricks

When I graduated from college with my Bachelors in CS, I knew next to nothing about successfully using Visual Studio, or any other visual debugger for that matter, for debugging. In fact, the majority of my debugging experiences involved liberal use of printf and reviewing output logs, which I suppose works to a degree, but it’s just not nearly as powerful as using Visual Studio.

Since then, from my experiences both at National Instruments, as well as working on the Visual Studio Platform team at Microsoft, I have learned a lot of neat tricks when using Visual Studio for debugging both managed and unmanaged code.

How to create and use a debugging project

I never knew you could do this until I joined Microsoft. If you want to create a “debugging project”, all you really have to do is File -> Open Project, and then find the executable you want to debug. Voila, when you hit F5, your “project” will automatically run the executable and attach to it. This is really handy for cases when you can’t attach to an already running process, because you need to attach as soon as possible before any loading takes place. If you edit your project properties you can customize the kind of debugging you do.

Attach to a running process

When you’re using Visual Studio to write, build, and run your application, you don’t have to do this, because you can just build your code and then run it like any normal project. However, if you’re debugging in a production environment, with a sizable codebase that doesn’t build in Visual Studio, you don’t really have this option. Instead, what you can do is load the source code you’re interested in, set breakpoints, and then attach to an already running application to do your debugging. This works remarkably well, and you don’t have to load the entire project into VS.

To do this, choose Debug -> Attach to Process, and find the name of the currently running executable that you want to debug. Make sure that you also click on the Select button to pick the specific type of debugging you want to do, namely Managed, Native, or both. I usually do both, but only because I usually debug mixed-mode applications. If your project is entirely managed or entirely native then you can improve debugging performance by picking whichever one applies to you.

Disable Just My Code

Just My Code is one of the many default settings that I can’t stand because I always want to turn it off, just like “Hide extensions for known file types” and “Insert tabs”. I guess the idea behind Just My Code is that the average programmer might not care if some low-level library is throwing exceptions, they only want to focus on their own code. But we don’t want to be average programmers, we want to be rockstar programmers, so turn it off and you can actually debug into the programs you’re attaching to as deep as you need to go. Trust me, turn this off.

Loading Symbols

The next step after disabling Just My Code is usually adjusting your symbol settings and making sure that your symbols are loaded. If you go to Debug -> Windows -> Modules after running or attaching to your executable, you can see a list of every assembly or DLL loaded by the application, and whether or not symbols have been loaded for that module, among other things. There are three things you usually need for debugging:

  1. Source code
  2. The assemblies or DLLs being debugged
  3. Program Database (pdb) files

The PDB files are the files built for Debug builds which actually contains the debugging information, otherwise known as symbols. These files are the link between your binary module and your textual source code, so loading them means that you can now set breakpoints in your source code and the Visual Studio debugger will honor those breakpoints and allow you to debug.

If your symbols aren’t being loaded for the module you’re interested in, it’s probably just because Visual Studio doesn’t know where to look for your PDBs. Right-click on the Modules window and choose Symbol Settings, and you can give Visual Studio a list of directories to look in for PDB files. If some of these symbols live on the network, it is also usually a good idea to choose a local directory as a symbol cache so that you only have to download symbols once. If “Load symbols using the updated settings when this dialog is closed” is checked, Visual Studio will attempt to load every single PDB it can find in the directories you specified. Sometimes that’s fine but other times you may wish to uncheck this so that you don’t load symbols for everything in the world when you only care about a single module.

Disabling Native Images

Native Images are basically managed assemblies compiled into processor-specific machine code. The .NET runtime can use these natives images, which are stored in the native image cache, instead of having to use the just-in-time compiler every time a managed assembly is loaded. Application developers can use ngen or the Native Image Service to generate these native images.

The bad thing about native images however is that, because they are compiled into processor-specific optimized machine code, they are much harder to debug. So in some cases you might want to disable these native images when running your Visual Studio debugger. The instructions are available here: Reference Source FAQ, but essentially what you have to do is set the environment variable COMPLUS_ZapDisable=1 in your environment before launching Visual Studio, and then disable the Visual Studio Hosting Process. This will cause Visual Studio to ignore the native images and use the managed assemblies instead, so now you can debug your previously optimized code.

Set Next Statement

Set Next Statement is a powerful debugging technique that I had ignored until I saw someone use it, and finally I realized why it might come in handy. When you’re debugging in Visual Studio, and the application is paused by the debugger, you can elect to skip the natural execution path of the program and choose the next statement your program will execute. All you have to do is right-click in the text editor on the next statement you want to run, select Set Next Statement, and Visual Studio automatically skips there next instead of executing the current line, changing the program’s instruction pointer.

Why would you want to do this? Maybe you want to see what would have happened if a certain condition was met and step into an if or else that wouldn’t have occurred otherwise. Maybe you want to see what would happen if you skip some code or execute it again. The possibilities are endless, and you don’t even have to recompile your code to do it.

Modify variables at runtime

This technique is kind of similar to the previous, in that you’re modifying the natural execution of a running program by changing variable values, or even values in memory, at runtime. Simply find the variable you’re interested in, either via Locals, Autos, or the Watch window, double-click on its value, and change it to whatever you want. Similarly, if you know the address of a pointer to memory you’d like to change, you can open up the Memory window, type in the hexadecimal address, and use the hex-editor to modify memory values.

Like the previous technique, you can use this to see what would have happened if a certain variable was set to something else. For example, you could be calling a function which is returning an incorrect value, but you want to double-check to make sure your code would work correctly if the correct value was actually being returned. Simply change the value after you call the function, and now you can find out.

Freeze and thaw threads

In multi-threaded applications, it’s extremely important to make sure that no matter what, your program cannot get into a deadlock situation where two threads block each other from being able to continue executing. Unfortunately, this is very difficult to prove, and simply running your program and verifying that it didn’t crash isn’t enough, because of the indeterministic nature of multi-threading. So how do you test/verify your code? Use the Threads window in Visual Studio and use it to freeze/thaw threads.

When you open the Threads window, and the program is paused, you will see a list of the currently executing threads for your process. Each thread has an ID, a category, a name, a location, and a priority. When you’re debugging a multithreaded application, you want to brainstorm ways in which to deterministically control which thread executes which code in which order, so after you’ve broken into your first breakpoint, you can freeze that thread and then let the other thread catch up to the point where you want to freeze it. If you pick the right freeze/thaw points for each thread, and your program has the possibility of deadlock, you should be able to force the program into it by controlling the execution timing. If you can successfully do this, your code is flawed and must be fixed.

Determine which DLL or assembly to load based on a virtual function pointer

I learned this technique very recently from a colleague at Microsoft. Sometimes you might be debugging an application, and you want to step into a particular virtual function call, but you can’t because Visual Studio hasn’t loaded the symbols for whatever module the function is located in. Also, you don’t actually know offhand which DLL it is, and you don’t want to just load every symbol in the application because it takes too long and slows you down too much.

So here’s what you can do, sometimes. Let’s say you have a pointer to a virtual class which implements the method you’re interested in. Use Intellisense to find out more about that pointer, until you find the virtual function table. Now you have a memory address for where a particular method implementation is located. Open up your Modules window in Visual Studio, and sort by Address. Find out which address range corresponds to the virtual function pointer, and that row is the module you’re looking for. Right-click on it and choose to Load Symbols, and now the next time you try to step into that function call, it will succeed because the symbols are now loaded. Here’s a screenshot of this in action:


So there you have it, some of my favorite Visual Studio debugging tricks. Since I’m pretty new to the Visual Studio Platform team I am sure I will learn new tricks as I go along, so I will be sure to post about them as I discover them.

Published by


Seattleite. Climber. Snowboarder. Traveler. Party rocker. Technologist. Spanish enthusiast. Fun-seeker.

8 thoughts on “My Favorite Visual Studio Debugger Tricks”

  1. Come on man. Dragging the yellow arrow is pretty cool. This makes it really easy to do things like move the execution past a status check. No right clicking involved.


  2. Thanks for making this page. You wouldn't happen to know how to step into a virtual function of a class would you? i.e.class SomeClass{public: virtual void someFunc(); …}SomeClass * s = new SomeClass;s->someFunc(); // step into this functionThe MSDN site says that this is not possible but you “Determine which DLL or assembly to load based on a virtual function pointer” section makes it sound as if it might be possible. It seems like there should be some way as inheritance and polymorphism that can stem from this kind of coding is critical in developing good OOP code. Any help would be tremendously appreciated. Thank you!


  3. Could you post a link to the MSDN article you’re referring to? I’m pretty sure that you can step into a virtual function call (I just tried it), but there are a few reasons why Visual Studio might not be able to do it, depending on the situation.For example, if the virtual function is defined in a module you haven’t loaded symbols for, that likely won’t work. Or, if you have Just My Code enabled, it may not work. If you’ve already determined which module contains the virtual function pointer you’re looking for, you should load symbols for that module and try to set a breakpoint in the source for the method you want to debug. If you don’t have symbols, or you don’t have source, then you may be out of luck there.


  4. Thank you very much for your quick response. The MSDN site that I was pointed to from another forum that perhaps states it most clearly is: halfway down the it reads: “In native code, Step Into Specific does not work with virtual functions.”However it does say “native code” and hence this may not actually be appropriate.The problem I’m experiencing is with a older but important program written originally in (2003). Since your last post I was able to create a test program in VS 2003 and VS 2008 and I do not appear to have the same issue in either version, therefore I’m guessing that it maybe a project propety?I have converted the older program into a VS 2008 .NET Framework 3.5 version as well just to be sure and I did check the “Just My Code” idea you had as well but in both the VS 2003 and the VS 2008 versions I have not been able to go into virtual functions called via a class pointer, regardless of whether I have breakpoints set in the virtual function or not. This appears to be a non-unique problem as I have found it on several forums but your site was the first (and only) one that has offered any hope for a solution. To describe the problem better, when I try to step into the virtual function while running in debug mode, the error window that pops-up reads:“There is no source code available for the current location.”And the error window offers “OK”, “Show Disassembly” buttons and in the VS 2003 version a “Help” button as well. Saying OK and pressing F5 allows the code of the virtual function to still execute properly, even if the class pointer is pointing to a derived class object, but I can never step inside the virtual function.The only files listed in the Modules windows are my executable file (whose Symbols are loaded) and mscorlib.dll which I am unfamilar with but is located in the\framework\v.1.1.4322 folderOnce again I really greatly appreciate if you can be of any help with this and thank you once again for your very prompt past response.


  5. Ahh, I see. I think Step Into Specific is different from Step Into; to use it you just right-click on your source code on a multiple-function call eg. Func1(Func2()), and pick which function you want to step into. I’m not sure why it doesn’t work for native virtual methods but it probably doesn’t apply to your situation.So are you using .NET in C++ via Managed C++? Or C++/CLI? I can probably do a test to see if I can step into .NET virtual methods on a test project. Mscorlib.dll stands for Multilanguage Standard Common Object Runtime Library, but it’s just the .NET runtime library. Version 1.1 of that library corresponds to Visual Studio 2003’s version of the framework. That’s to be expected.One thing you might try is to go ahead and view the assembly; I think you can right-click on the assembly source and choose Go to Source Code, and you should be able to choose the path to your source. If it complains that the source doesn’t match the module, then that would explain your problem as well. If you’ve changed the source without rebuilding your executable/symbols won’t match your source anymore. Does your solution contain multiple (dependent) projects or is it just one project?


  6. I created a test C++/CLI (VS 2005 and later) console application, and here's the source. I found if I put a breakpoint on the System::Console::WriteLine line and hit F11 after breaking, it steps into MyClass::ReturnTrue:#include “stdafx.h”using namespace System;public ref class VirtualClass abstract{public: VirtualClass() { } virtual bool ReturnTrue() abstract;};public ref class MyClass : public VirtualClass{public: MyClass() { } virtual bool ReturnTrue() override { return true; }};int main(array ^args){ MyClass^ m = gcnew MyClass(); VirtualClass^ v = dynamic_cast(m); System::Console::WriteLine(v->ReturnTrue().ToString()); return 0;}


  7. Thank you very much for your help, however, I found that the only way I was able to fix the problem was to create a brand new project and then copy all of my code and content into this new project. Then I was able to step into virtual functions without a problem. It was a bit time consuming but at least it worked. Thank you once again.


  8. Amazing – I google for COMPLUS_ZapDisable because I need to use it for VS2010 debugging – and I see this blog post from a former colleague from AE @ NI! Crazy world… you still at Microsoft?


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s