When you’re dealing with a large program and multiple developers, it’s not always obvious how and when certain things get executed. One of the very useful ways to debug unexpected behaviour is to set a breakpoint on a suspect line of code and examine the callstack (or stack trace) when it gets hit to see the execution path.
For infrequent events, it’s not always desirable to halt the entire program while you do that though. Instead, you can tell Visual Studio to write the callstack to the output when the breakpoint gets hit, and immediately continue execution.
Supported versions of Visual Studio
I’m working with C++ in Visual Studio 2010 Professional. I believe the procedure is roughly the same on VS2012.
To set your breakpoint, do the following:
- Create a normal breakpoint (if you don’t have one already)
- Right-click the breakpoint marker
- On the context menu, click “When Hit…”
- Tick the checkbox labelled “Print a message”
- In the text box below it, enter
- Optionally add some other text to identify the breakpoint
- Make sure “Continue execution” is ticked
- Click OK
The “When Hit…” dialog should look like this:
Run your program in Debug mode. When the breakpoint is hit, it should output the callstack to the Output pane in Visual Studio. If the Output pane isn’t visible, you can usually enable it from the View menu. Below is an example of a call stack which was outputted using this technique:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 MessageServer.exe!Protocol::clear() MessageServer.exe!Protocol::~Protocol() MessageServer.exe!Interface::~Interface() MessageServer.exe!Interface::`scalar deleting destructor'() MessageServer.exe!std::_Destroy<Interface>() MessageServer.exe!std::allocator<Interface>::destroy() MessageServer.exe!std::_Dest_val<std::allocator<Interface>,Interface>() MessageServer.exe!std::vector<Interface,std::allocator<Interface> >::pop_back() MessageServer.exe!Connection::negotiateHandler() MessageServer.exe!Connection::send() MessageServer.exe!ConnectionManager::broadcastToAll() MessageServer.exe!main() MessageServer.exe!__tmainCRTStartup() MessageServer.exe!mainCRTStartup() kernel32.dll!7632ed5c() [Frames below may be incorrect and/or missing, no symbols loaded for kernel32.dll] ntdll.dll!777137eb() ntdll.dll!777137be()
There’s a lot more you can do with breakpoints, including breaking after a certain number of hits, or when other conditions are met. For more information, check out this article on MSDN: