I'm not sure how Rust's support is here, but in my experience it's the exact opposite. Debuggers with var-watch or conditional breakpoints can do this (and a heck of a lot more) on the fly, and that's almost always faster than re-compiling and running. Even at the extreme-worst case, you can be a print-debugger with a debugger without needing to rebuild each time, just re-run.
X86 is pretty orderly so you usually don't see that class of bugs until you start getting on other architectures but when you do man is it nasty. C/C++ volatile comes to mind particularly. MSCV makes it atomic and fenced which isn't the case pretty much anywhere else.
Also debuggers don't help you with the 2nd/3rd order effects when you need to trace something that's falling over across 5-6 different systems. With print based debugging I can format + graph that stuff much faster than a debugger can show me.
Like I said, different tools for different uses. It's just important to know the right tool so that everything doesn't look like a nail.
Yes, that is definitely true. But so does calling a printing func that does IO, since it often involves system-wide locks - I'm sure many here have encountered bugs that go away when print statements are added. But debuggers are definitely more invasive / have stronger side effects, and have no workaround, yea.
Multiple systems: sorta. Past (legitimately shallow) multi-process debugging that I've done has been pretty easy IMO, you just add a conditional breakpoint on the IPC you want and then enable the breakpoints you care about. Only slightly more complicated than multi-thread since the source isn't all in one UI. Printing is language agnostic tho, so it's at least a viable fallback in all cases, which does make it a lot more common.
---
To be clear, I'm not saying there's never a need for in-bin "debugging" with prints, data collection of some kind, etc. You can do stuff that's infeasible from the outside, it'll always have some place, and some languages/ecosystems give you no option. Just that it's far later than most people encounter, when a sophisticated debugger exists. E.g. printf debugging in Java that I encounter is usually due to a lack of understanding of what the debugger can do, not for any real benefit.
> the only way to safely root-cause to to stash away data somewhere in mem and print it later as flushes/fences/etc change behavior.
Dude, I literally called that out in the root post ;).
I think a lot of debugger vs printf-style debugging is a matter of preference and familiarity. I'm used to debugging embedded or distributed systems where debugger support is not so great, so I've gotten used to other techniques (including printf-style stuff). But a lot of people love using debuggers, and I find it elitist to tell them they're wrong.
You'd be impressed with the power of formatted printf + excel. Solved some fun issues like quaternion interpolation normalization via graphing and the like.
Don't get me wrong, they're handy but I find them much more useful for stepping flow than root-causing errors.
Also if you're dealing with race conditions the only way to safely root-cause to to stash away data somewhere in mem and print it later as flushes/fences/etc change behavior. Debuggers make that even worse.
Love my debuggers for behavior issues but each tool has it's place.