In Visual Studio 2017 release 15.8 Preview 3 we’re announcing support for Just My Code stepping for C++. In addition to previously supported callstack filtering, the Visual Studio debugger now also supports stepping over non-user-code. As you “Step In”, for example in an algorithm from the Standard library with a custom predicate or in a Win32 API that has a user callback, the debugger will conveniently step into the predicate or callback you provided rather than the library code that will eventually call your code.
After the very warm reception of our debugging improvements in stepping in std::function calls announced last year at CppCon 2017, the team has been working on an universal solution for this debugging challenge that does not require any annotations in library code. 15.8 Preview 3 is available today with this support and we are looking forward to your feedback.
How to enable Just My Code stepping (JMC)
Just My Code stepping for C++ has the following requirements:
- your program is compiled with a new MSVC compiler switch: /JMC. JMC is now on by default for MSBuild projects in all Debug configurations, so just make sure you recompile your project using the latest MSVC compilers in 15.8 Preview 3 or later.
- the PDB for the binary containing the user code is loaded by the debugger, and
- JMC is enabled in Tools > Options > Debugging > General > Enable Just My Code (which is the default).
New “Step In” behavior
When JMC is enabled, the debugger will keep track of which code is user code or system/library code. When stepping into a function that has PDB information, execution will resume until another function that is marked as user code is reached or the current function completes its execution. What this means in practice is that to get to your code, you don’t have to spend your time stepping over countless lines of library code that you’re not interested in or, what happens more often, you can stop juggling giant lists of breakpoints spread all over your codebase.
For example, in the snippet below, without JMC, if you are ambitious enough to “Step In” until you reach the predicate passed as a parameter to the Standard library algorithm, you will have to press F11 (Step In) 140 times! With JMC, it is just one “Step In” command invocation.
STL algorithms | |
Another example is stepping into Win32 API callbacks. Without JMC, the debugger is not able to tell that some user code will eventually execute, so it steps over the Win32 API call completely without stepping into the user-defined callback. JMC correctly identifies the callback as user code and stops the debugger appropriately.
Win32 API callbacks | |
Step Into Specific
To explicitly step into a call that may be non-user code, you can take advantage of the “Step Into Specific” command available in the editor’s context menu. This allows you to select a specific function (user code or not) that you want to step into:
Configuring Just My Code for additional 3rd party libraries
The default set of modules and source files that the C++ debugger considers non-user code is encoded in the default.natjmc file under %VSInstallDir%\Common7\Packages\Debugger\Visualizers and it specifies WinSDK, CRT, STL and ATL/MFC among other things.
You can customize this set of modules and source files by either:
- modifying the central list in %VSInstallDir%\Common7\Packages\Debugger\Visualizers\default.natjmc or
- by creating any number of user-specific .natjmc files under the %USERPROFILE%\Documents\Visual Studio 2017\Visualizers folder.
For example, to treat all Boost libraries as non-user code, you can create a boost.natjmc in the above folder with the following content.
<?xml version="1.0" encoding="utf-8"?> <NonUserCode> <File Name="*\boost\*" /> </NonUserCode>
You don’t need to rebuild your user code for these changes to kick in. In the next debugging session, stepping into code that uses Boost will step over the Boost library code and only stop execution if some user code is found on the callstack.
For more details on the .natjmc file format, see the C++ Just My Code documentation page. Note that the .natjmc format also supports marking code as non-user code based on function name, but for stepping performance reasons, we do not recommend using this functionality for functions that are called often or for large group of functions (‘Function’ rules are much slower than ‘Module’ or ‘File’ rules).
3rd party libraries |
Under the covers
As mentioned above, JMC functionality is only available for user-code compiled with the new MSVC compiler switch /JMC. This new switch is already on by default for MSBuild projects in Debug configurations. If you’re using a different build system, you will want to make sure you manually add the off-by-default /JMC switch to the debug builds of your project.
/JMC is supported only for binaries that link against the CRT.
To explicitly turn off JMC, you can use the /JMC- switch.
Give us your feedback!
This release is the first Visual Studio 2017 Preview supporting Just My Code stepping. Your feedback is a critical part of ensuring that we can deliver a delightful debugging experience. For any questions, reach out to us via Twitter at @visualc or via email at visualcpp@microsoft.com. For any issues or suggestions, please let us know via Help > Send Feedback > Report a Problem in the IDE.
Great tool, really appreciate it! However, I would like to make a *.natjmc file available for all members of my team by putting it into a git repository. How do I do this so that debugger can notice it?