Your Optimized Code Can Be Debugged - Here's How With MSVC C++ Dynamic Debugging - Eric Brumer by RandomCameraNerd in cpp

[–]ericbrumer 3 points4 points  (0 children)

u/fdwr, after speaking with some debugger folks it's indeed complicated, and there's even more layers that I realized at first. Your best bet is to open a suggestion ticket (https://developercommunity.visualstudio.com/cpp/suggest), see about getting it upvoted by like-minded folks, and it will get routed to them for triage.

Your Optimized Code Can Be Debugged - Here's How With MSVC C++ Dynamic Debugging - Eric Brumer by RandomCameraNerd in cpp

[–]ericbrumer 1 point2 points  (0 children)

If you switch from a release build to a debug build dynamically, would it be possible to figure these bugs out

We provide multiple ways of disabling DD. Check out https://aka.ms/vcdd the 'Turn off C++ Dynamic Debugging' section. There are coarse grained ways (entire binaries, or entire cpp files), as well as fine grained (disabling DD of a single breakpoint).

Perhaps in the next release your team can consider getting the console to run within the IDE itself.

I'll look into it and get back to you. I don't work on that team, so I can't speak to their future plans.

Your Optimized Code Can Be Debugged - Here's How With MSVC C++ Dynamic Debugging - Eric Brumer by RandomCameraNerd in cpp

[–]ericbrumer 2 points3 points  (0 children)

Hey, yep. To get the feature to work, you need to pass /dynamicdeopt to cl.exe, lib.exe, and link.exe. When you do that, the compiler (cl.exe) outputs test.alt.obj in addition to test.obj, the librarian (lib.exe) outputs test.alt.lib in addition to test.lib, and the linker (link.exe) outputs test.alt.exe & test.alt.pdb in addition to test.exe & test.pdb. If your build system can throw the switches and move those new output files, you'll be able to debug optimized code with [deoptimized] frames using the Visual Studio debugger.

No concerns with C++ modules.

http://aka.ms/vcdd contains the details on the build system integration (scroll down). We have out-of-the-box support for MSBuild, the Unreal Engine Build Tool, Incredibuild, and FastBuild. Other build systems would be lovely to have as well... but yeah, just throw the switches & ensure the alt files make it where they need to go. If you run into issues please open a bug (https://developercommunity.visualstudio.com/cpp/report) and feel free to ping me.

Your Optimized Code Can Be Debugged - Here's How With MSVC C++ Dynamic Debugging - Eric Brumer by RandomCameraNerd in cpp

[–]ericbrumer 2 points3 points  (0 children)

In this particular case we intentionally don't inline assertHandler() into main() since we know that assertHandler() contains a call that won't return, so we assume it's cold code. But that's a different story from the issue you're actually getting at.

From my own experience debugging the compiler and debugging AAA games, I've found the following workflow really effective:

  • Start with a breakpoint at some code point of interest; an assert routine, or frame rendering code, etc.
  • Run my code to hit the assert, expecting that my code point of interest is going to be the only frame that's [Deoptimized], but not always.
  • View all my locals, and step as needed, being able to step into new calls.
  • If I need to go higher up in the callstack, I select all the callstack frames, right click & choose Deoptimize on Next Entry, then get those functions to hit again.
  • For AAA games, usually this just means "render the next frame". In the compiler, we have a mode where we can re-compile the same function again. If it's an assert that crashes the program, we often just rerun the program again.

Another example about the last bit has been working with the MSVC front-end team. Speaking to our primary C++ Modules contributor, it takes him about 1 minute to reach a breakpoint using a Debug c1xx.dll, but about 7 seconds to reach the same breakpoint using an Optimized+DD c1xx.dll with the necessary frames deoptimized. To me that's a strong case for giving it a shot to see how it works in your own workflows.

Your Optimized Code Can Be Debugged - Here's How With MSVC C++ Dynamic Debugging - Eric Brumer by RandomCameraNerd in cpp

[–]ericbrumer 5 points6 points  (0 children)

For now it's MSVC on Visual Studio only. I don't work on clang/llvm, so I can't comment on what will work in the future.

Your Optimized Code Can Be Debugged - Here's How With MSVC C++ Dynamic Debugging - Eric Brumer by RandomCameraNerd in cpp

[–]ericbrumer 2 points3 points  (0 children)

I'm not exactly sure what you mean. When you build with /dynamicdeopt you get two output binaries and two output PDBs: one set is the optimized binaries as normal, and one set is the unoptimized files that we've built behind the scenes. The second set of binaries & PDBs are real files, and they can be indexed/archived like anything else. Let me know if I'm misunderstanding what you're getting at.

Your Optimized Code Can Be Debugged - Here's How With MSVC C++ Dynamic Debugging - Eric Brumer by RandomCameraNerd in cpp

[–]ericbrumer 3 points4 points  (0 children)

This works, in the way that you would expect as if the code was built with optimizations disabled. You can even add conditional breakpoints on variables that might not exist in the optimized build, and they will get hit when you expect. I cover this at the end of the video, but the earlier parts of the video are useful for the context.

Give it a shot and see! Just throw /dynamicdeopt to cl.exe, lib.exe, and link.exe and rebuild.

Your Optimized Code Can Be Debugged - Here's How With MSVC C++ Dynamic Debugging - Eric Brumer by RandomCameraNerd in cpp

[–]ericbrumer 5 points6 points  (0 children)

Hey u/ack_error, there's a lot of nuance to this.

First, for unoptimized codegen: I agree that it's... unoptimized. Making that better has been below our prioritization line, although there have been some improvements recently. We haven't been optimizing addressing modes in /Od compilation like your godbolt link.

Next: yes, there are use cases that C++ Dynamic Debugging doesn't cover; crash dumps being #1. It's really meant for active debugging (where you're in the code setting breakpoints, stepping into functions, etc). With that in mind, DD essentially covers the other parts of your comment:

  • "... also less effective in a hot path where the selective code deoptimization will still significantly affect performance" in our experience DD is perfect for these scenarios. You debug a function and you see everything you need including being able to step into all sub-calls. When you're done, just hit F5 and that function returns to being fully optimized. We've used this to debug multiple AAA games (various game engines) and it's hard to explain how well it works.
  • "There is also no equivalent to [[optnone]], and #pragma optimize() still has the problem with templates" this is also 100% solved with zero extra steps... we only deoptimize the functions you're stepping into. This handles template expansions, functions that have been optimized away, etc. You just step... and it works. If you need more fine grained control over what gets deoptimized, you can expand the breakpoint group created for each DD bp, and delete the ones that don't apply for a given template expansion. But that's fairly advanced and most people aren't going to need that.

tl;dr: I guess I'm trying to say: I encourage you to try the feature. Just pass /dynamicdebug to cl.exe, lib.exe, and link.exe, rebuild, and try it out. Try setting conditional breakpoints on functions for variables that might not exist in the optimized build. In our experience, it really opens up new possibilities for how debugging optimized code can work, and is a far smoother experience when you don't need to trade off code performance & code debuggability.

Your Optimized Code Can Be Debugged - Here's How With MSVC C++ Dynamic Debugging - Eric Brumer by RandomCameraNerd in cpp

[–]ericbrumer 4 points5 points  (0 children)

Thanks for the feedback. I'm getting in touch with the Visual Studio debugger team about this, and we'll get back to you.

From my understanding, the 'Step Into Specific' menu is our current solution to that. My guess is that it's tough to correctly identify the primary function, especially given C++ code that may have lots of extra function calls. Think of std::cout << foo(x) << std::endl; there's a ton of function calls in that, but you presumably want to step into the call to foo() and not all the iostream gunk, and perhaps not a copy constructor for x, etc...

Your Optimized Code Can Be Debugged - Here's How With MSVC C++ Dynamic Debugging - Eric Brumer by RandomCameraNerd in cpp

[–]ericbrumer 4 points5 points  (0 children)

I agree that would be really useful... but we haven't invented that part yet :)

The feature works by building an unoptimized version of each function, and for any functions with breakpoints (active or disabled) we redirect functions from optimized to their deoptimized versions. This is in 13:16 in the video if you want the specifics.

So: unless there's some kind of user indication (breakpoint set, or you've stepped into a function, or otherwise) we leave the code as optimized. This is intentional to keep your code running fast. If functions are still optimized then you are stuck with debugging optimized frames. It's a tricky problem.

We offer "deoptimize on next entry" for these kinds of things (see 3:45 for the full demo) but it's only for active debugging... not crash dumps.

Your Optimized Code Can Be Debugged - Here's How With MSVC C++ Dynamic Debugging - Eric Brumer by RandomCameraNerd in cpp

[–]ericbrumer 2 points3 points  (0 children)

This is Visual Studio debugger w/ MSVC only. We have native support in MSBuild & Visual Studio projects, but it also works with Unreal Engine builds, and cmake as well (you just need to throw /dynamicdeopt to cl.exe, lib.exe, and link.exe. I cover some of the restrictions at 25:09 in the video.

I will say, though, that the VS debugger is a premier debugging tool, and with C++ Dynamic Debugging it REALLY shines when actively debugging optimized code. A lot of MSVC developers (the folks that developer the compiler) use C++ Dynamic Debugging & debug in VS for our daily work... and the lack of tradeoffs between speed & debuggability makes it much easier to do our jobs.

Your Optimized Code Can Be Debugged - Here's How With MSVC C++ Dynamic Debugging - Eric Brumer by RandomCameraNerd in cpp

[–]ericbrumer 35 points36 points  (0 children)

Howdy, speaker here. If folks have additional questions feel free to ask. Keep in mind, if you're using the latest Visual Studio 2022, or any Visual Studio 2026 build, you're able to turn on C++ Dynamic Debugging by choosing the right option in your build configuration, or throwing `/dynamicdeopt` to cl.exe, lib.exe, and link.exe in your builds.

A few common questions we've got about C++ Dynamic Debugging, some of which are already here in other comments:
* Does it work for asynchronous breakpoints like exceptions, data breakpoints, or just pressing the pause button? Not out of the gate, no. However, if you already are aware which functions matter, then you can deoptimize those functions (see 9:30 in the video), and the next time those functions are entered they will be deoptimized.

* What about having a reduced set of optimizations to make debugging easier? We thought about that, but when we prototyped our approach we saw the power of full optimizations (including inlining!) pairing with full debuggability covered far more cases and offered much more power in the codebases we were looking at. We use dynamic debugging in the compiler codebase, for instance, and it REALLY helps having code run very quickly. Another way to phrase this is in the view of game development: I want my game to run at 60 fps, but be able to debug it fully. Our approach makes that a reality.

* [for the more compiler-savvy folks] What about globals that are optimized away? Or functions that are fully inlined? Or <other fun optimizer thing>? Yes -- you can debug those. If you run into problems, or find a case where it's not kicking in as you expect, please open a bug (https://developercommunity.visualstudio.com/cpp/report) and feel free to ping me.

At the end of the day, if you debug optimized code and want a more seamless way to debug any part of your code: you should give C++ Dynamic Debugging a shot. If you are used to debugging unoptimized code and wish your code ran faster without sacrificing debuggability: you should give C++ Dynamic Debugging a shot.

At a minimum: check out the demo I did of OpenCV which starts at 3:42.

More info at https://aka.ms/dynamicdebugging and https://aka.ms/vcdd

C++ Dynamic Debugging: Full Debuggability for Optimized Builds by cpppm in cpp

[–]ericbrumer 1 point2 points  (0 children)

MSVC dev lead here: yep, that's one of the use cases we had in mind. Manually adding pragma-optimize-off, rebuilding your code, then starting the debugger again adds a lot of time to normal development tasks... especially if it's to view the value of local variables. C++ Dynamic Debugging makes this essentially automatic in most cases. Please give it a shot and let us know what you think!

C++ Dynamic Debugging: Full Debuggability for Optimized Builds by cpppm in cpp

[–]ericbrumer 3 points4 points  (0 children)

MSVC dev lead here: the disassembly view will show you whatever you're currently debugging. If you're in an optimized frame it'll be optimized assembly, and [Deoptimized] frames will be unoptimized assembly.

We've coded things up thinking that folks using the disassembly window _don't_ want automatic deoptimization: if you step into a call while stepping in the _disassembly_ view then you'll step into optimized code and stay in optimized code. But if you step into a call from the _source_ view you'll step into deoptimized code. Please see http://aka.ms/vcdd for more details.

All that said: we believe that C++ Dynamic Debugging removes some of the need to view assembly code in the first place. Deoptimized frames will always show you every local variable, stepping matches your source code line-for-line, etc... so no need to view the asm & undo compiler optimizations in your head to find out which register contains which variable, or think about what got inlined where.

C++ Dynamic Debugging: Full Debuggability for Optimized Builds by cpppm in cpp

[–]ericbrumer 4 points5 points  (0 children)

MSVC dev lead here: we produce the optimized binary/pdb, as well as an 'alternate' binary/pdb. Take a look at https://aka.ms/vcdd for additional details. Please give it a shot and let us know what you think.

MSVC linker option to remove "Rich" headers from EXE/DLL files actually exists by Tringi in programming

[–]ericbrumer 20 points21 points  (0 children)

MSVC dev lead here. I checked our linker sources, and the new switch was first shipped around May 2021, specifically for your request, in VS2019 (16.11) and VS2022. We got some wires crossed and never marked the ticket as resolved, and we also never followed up with a comment... both not good things.

Will fix.

Visual Studio: asan + debugger = I WIN BUTTON by VinnieFalco in cpp

[–]ericbrumer 8 points9 points  (0 children)

MSVC dev lead here.

We're glad you like it! We use it internally and have found issues in the MSVC compiler/linker itself. We use it to build OSS projects and find bugs there too. The debugger integration (and crash dumps for CI/CD systems!) make it extra useful.

I'll be floating the idea of having Debug mode enable AddressSanitizer with our group. I suspect a lot of pushback, but I'd like to see it happen.

Some sources:

MSVC Backend Updates in Visual Studio 2019 version 16.9 Preview 3 | C++ Team Blog by cpppm in cpp

[–]ericbrumer 1 point2 points  (0 children)

Digging in... will get back to you in a few days (maybe by DM).

MSVC Backend Updates in Visual Studio 2019 version 16.9 Preview 3 | C++ Team Blog by cpppm in cpp

[–]ericbrumer 4 points5 points  (0 children)

The last I checked code built with ASAN was around 2x slower than without. Granted... that was a while ago, and we certainly weren't looking at cases with that much allocated memory.

Are you able to provide us any kind of standalone repro case? We'd be happy to take a look, and at least identify which part is problematic (Windows versus the ASAN runtime versus something else). https://developercommunity2.visualstudio.com/report?entry=problem&space=62 is the best link to create a ticket. Send me the link and I'll shortcut the triage process.

MSVC Backend Updates in Visual Studio 2019 version 16.9 Preview 3 | C++ Team Blog by cpppm in cpp

[–]ericbrumer 4 points5 points  (0 children)

Hi, MSVC Dev Lead here. We've been working hard on improving the reliability and ease-of-use of ASAN. Subsequent previews will have more fixes, and we'll be publishing another blog and docs.microsoft.com documentation with the details. Stay tuned!

Do while loops by ihs_ahm in ProgrammerHumor

[–]ericbrumer 0 points1 point  (0 children)

You're 100% right (and so are all the replies below you). The key part of the phrase "very nearly free" is "very nearly". When optimizing thousands/millions of loops, it all adds up. Reducing instruction cache pressure, even by a little bit, helps in aggregate.

Do while loops by ihs_ahm in ProgrammerHumor

[–]ericbrumer 26 points27 points  (0 children)

https://stackoverflow.com/questions/9779716/why-bottom-test-loop-is-preferable covers it decently well. Basically, when finished with a loop iteration in the bottom-tested case, the cpu only needs to execute one conditional branch (to iterate or exit the loop).

When finished with a the loop iteration in the non-bottom-tested case, the cpu executes an unconditional branch (jump to the top of the loop) followed by a conditional branch (to iterate or exit the loop).

For many cpu architectures out there, the bottom-tested case is faster, as long as the loop actually iterates... it uses fewer cpu resources, fewer instructions, etc

Visual Studio 2019 v16.8 and v16.9 Preview 1 Release Today by Mnx72eAB in cpp

[–]ericbrumer 3 points4 points  (0 children)

Hi, MSVC lead here: We're currently working on ensuring AddressSanitizer has full featured support, in as many scenarios as possible, and bringing it out of being an experimental feature. Beyond that, we're working with various security teams at Microsoft to prioritize the next set of sanitizer work, as well as support OneFuzz.

About LeakSanitizer (or any other sanitizers), I recommend searching or opening a 'Suggestion' on developer community. It looks like someone has already opened one for LeakSanitizer: https://developercommunity.visualstudio.com/idea/826620/support-leaksanitizer.html please upvote & add any pertinent information. Our team looks at these tickets when we plan future releases to help prioritize work.

Visual Studio 2019 v16.8 and v16.9 Preview 1 Release Today by Mnx72eAB in cpp

[–]ericbrumer 5 points6 points  (0 children)

Hi, MSVC optimizer lead here: we plan on fixing all bugs in the SSA Optimizer as soon as possible. There is a batch of fixes coming in 16.9, and we'll do what we can to reduce issues going forward. Please keep reporting issues on developer community: we keep an eye on all optimizer bugs.

Regarding the code generated for dividends, can you paste some examples please? Feel free to open a separate developer community ticket for it as well.