What the feature does
Debugging optimized C++ code is a familiar pain. Locals show "optimized away," stepping jumps around, and inlined functions get skipped. The usual fix is to switch to a Debug build or sprinkle #pragma optimize into the code. Both can change performance enough to hide the bug you're chasing.
Microsoft's approach works at the function level. Its Learn documentation says that compiling with /dynamicdeopt produces the normal optimized binaries plus unoptimized ones for debugging. When you set a breakpoint or step into a function, including __forceinline functions, the debugger loads the unoptimized version of that function. The rest of the program stays optimized.
The feature first appeared in Visual Studio 2022 version 17.14 Preview 2, as announced around GDC 2025. Microsoft's current documentation also says it applies only to x64 projects.
How to turn it on
MSBuild projects (x64):
- Select the Release configuration.
- Open the project properties.
- Go to Configuration Properties > Advanced > Use C++ Dynamic Debugging and set it to Yes.
- Rebuild.
The release notes confirm these steps and note that this mode turns off Whole Program Optimization. The Learn walkthrough adds that the build may show diagnostic MSB8088, which flags the conflict with /GL. You can set Whole Program Optimization to Off yourself. Microsoft warns that this diagnostic could become an error in a future Visual Studio version.
CMake and other build systems: pass /dynamicdeopt to cl.exe, lib.exe and link.exe. Microsoft stresses that it must reach all of them. If it's missing from some .cpp files, libraries or binaries, behavior is inconsistent.
Unreal Engine 5.6 and later: Microsoft's blog says to set WindowsPlatform.bDynamicDebugging = true; in the target's .Target.cs file and rebuild. Learn also documents an alternative. You can add <bDynamicDebugging>true</bDynamicDebugging> to the WindowsPlatform section of BuildConfiguration.xml. For Unreal 5.5 and earlier, Learn says you need to cherry-pick Unreal Build Tool changes. You also need Unreal Build Accelerator from 5.6, or you must disable UBA.
Distributed builds: Microsoft says FastBuild and IncrediBuild are compatible. Learn names IncrediBuild 10.24 and FastBuild v1.15 as the supporting versions. Treat those as the documented baseline, not as a statement that other versions fail.
Behavior to know about
- Deoptimization happens on demand. Setting a breakpoint in a function or stepping into it deoptimizes it. Stepping over a function does not. You can also right-click frames in the Call Stack window and choose Deoptimize on next entry.
- Disabling a breakpoint isn't enough. A function stays deoptimized until you remove the breakpoint. Debug > Delete All Breakpoints returns everything to optimized.
- Deoptimized code is not Debug code. The documentation says the deoptimized version uses the same flags as the optimized one, apart from the optimization flags and
/dynamicdeopt. Asserts and other code that depends on debug-specific settings are not included. - You will see extra breakpoints. Many dynamic breakpoints are really two, one in the optimized binary and one in the
altbinary. - Build output grows. For a project named
test, you gettest.alt.obj,test.alt.exeandtest.alt.pdbnext to the normal files. Build distributors must deployc2dd.dllalongsidec2.dll.
Incompatible options
If you enable the feature through the IDE, Visual Studio turns off most conflicting switches for you. Switches you add manually to the command line are not overridden. Custom build systems need to check these themselves.
- Compiler:
/GL,/GH,/Gh,/ZI(/Ziis fine), all/RTCflags,/ZW, the/clrvariants,/fastcap, and/fsanitize=addressand kernel-address. Custom builds should also avoid/JMC. - Linker:
/DEBUG:FASTLINKand/INCREMENTAL./OPT:ICFis allowed, but Microsoft says the debugging experience may be poor.
The /ZI restriction is easy to trip over, because Edit and Continue-style Debug settings commonly use it. Microsoft's suggested pattern is a dedicated configuration, for example a ReleaseDD cloned from Release. For a faster Debug build, it suggests a DebugDD clone with optimizations on.
If breakpoints don't hit
Learn lists these checks:
- Confirm that the
.alt.exeand.alt.pdbfiles were built and sit in the same directory as the regular.exeand.pdb. - Open an x64 native Visual Studio command prompt and run
link /dump /headers yourapp.exe. Look for adeoptentry under Debug Directories. It should name the alt executable. - If the entry is missing, confirm
/dynamicdeoptis passed to the compiler, librarian and linker. - Remember that stepping out of a deoptimized frame can land you in optimized code. This happens unless the caller was deoptimized by its own breakpoint or step-in.
Turning it off selectively
- Clear Automatically deoptimize debugged functions when possible (.NET 8+, C++ Dynamic Debugging) under Tools > Options > Debugging > General.
- Clear the alt-binary breakpoint in a pair, so the other breakpoint breaks in optimized code.
- Step in through the Disassembly window, which doesn't deoptimize.
- Omit
/dynamicdeoptfrom the final link for third-party binaries you can't rebuild. - Rename or delete a binary's alt file to disable the feature for that binary.
- Omit the flag when building individual
.cppfiles.
What the announcement does and doesn't show
The launch post leans on testimonials from two Microsoft engineers. Michael Buschbeck of Microsoft Havok calls it a game changer for large game codebases. Bryce Hutchings of Microsoft Cloud Streaming, Mixed Reality, and Graphics says it works so seamlessly "you forget how much it's helping." These are endorsements from inside Microsoft, not independent benchmarks. The post gives no build-time numbers, no runtime overhead figures and no third-party evaluation.
The claim of "the best of both worlds" is also narrower than it sounds. Deoptimization is per function and on demand. Whole Program Optimization is off, so a build with the feature on is not identical to a fully optimized shipping build. Teams that rely on /GL or /OPT:ICF for release performance should compare a dynamic-debugging configuration against their shipping build before treating it as equivalent.
Some Microsoft documentation lags the announcement. When the research was done, several Learn pages, including the /DYNAMICDEOPT linker reference, still showed "Preview" in their titles and text. The linker page said the option enables C++ Dynamic Debugging (Preview). The release notes and the dated GA post are the current authority on status.
Who benefits
The main audience is game and graphics developers, along with anyone running large, performance-sensitive native codebases. For those teams, a Debug build may run too slowly to reproduce the problem. Microsoft's game-development page lists support from IncrediBuild, FastBuild, Unreal Engine and Xbox GDK.
If your Release build is x64 and avoids the incompatible switches, the trial is cheap. Add a cloned configuration, rebuild, set a breakpoint in a function that normally shows "optimized away," and see whether the locals appear.
References
- C++ Dynamic Debugging is now generally available Microsoft C++ Team Blog · 2026-11-12T16:49:13+00:00
- C++ Dynamic Debugging - Visual Studio (Windows) | Microsoft Learn learn.microsoft.com
- GDC 2025: C++ Dynamic Debugging: Full Debuggability for Optimized Builds developer.microsoft.com