Hacker News new | ask | show | jobs
by vvanders 2705 days ago
Honestly when I'm dealing with memory errors and undefined behaviors I can count on my hands the number of time a debugger saved me and the hundreds of times I've had to printf my way to victory thanks to 2/3/N-order effects that cascade to the final corruption.

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.

2 comments

>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.

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.

Your conditional breakpoint can change execution behavior thought flushing cache/icache in a way that doesn't reproduce.

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.

>Your conditional breakpoint can change execution behavior thought flushing cache/icache in a way that doesn't reproduce.

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.

> But so does calling a printing func that does IO, since it often involves system-wide locks

> 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 ;).

Memory races, yea. Logical races no. But yep - I'd forgotten the context, agreed :)
You should try it before making uneducated, general comments that don't add anything. Rust in CLion/IntelliJ using LLVM is terrible: breakpoints and stack callers work, but variables, llvm and the rest are 99% broken.
I prefer ASAN/UBSAN to either debuggers or printf-style debugging in such cases, but it's not always available.

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.

Yeah, I've never had that pleasure except in toy scenarios but they are cool tools! Usually I'm dealing with 2-3 vendors worth of cruft and platforms that aren't publicly available.

You'd be impressed with the power of formatted printf + excel. Solved some fun issues like quaternion interpolation normalization via graphing and the like.