6 ms·
I agree you should know how to use a debugger, however will also note that some companies mandate use of a specific IDE (or heavily encourage). I have seen dev
by fsociety 4y ago
I agree you should know how to use a debugger, however will also note that some companies mandate use of a specific IDE (or heavily encourage).
I have seen devs scoff at the thought of print debugging, but I recall that in systems programming there are many times you can’t use a debugger or need to rely on other tool.
I’d rather schools teach the concept of step debugging vs runtime debugging. Teach students to try to understand the code, make hypotheses, and verify them.
I have seen some people use a debugger solely because they only know how to step debug. Meaning they start from main or another entry point and step through every line of code.
My point being that, you can’t judge a developer by if they use print statements or a debugger. Judge them by the methodology of how they debug.
- solatic 4y ago> I have seen devs scoff at the thought of print debugging, but I recall that in systems programming there are many times you can’t use a debugger or need to rely on other tool. Not just systems programming, but fixing issues in scaled production systems as well. Have fun attaching a debugger to the process that got killed twenty minutes ago when the spot instance it was running on got reclaimed. If you don't collect telemetry, you're blind. Debuggers are a luxury that you get to enjoy for issues you have before you ship.
- ModernMech 4y ago> I have seen devs scoff at the thought of print debugging Next time they do, ask them to recommend a better method of debugging that works across generally all languages, compilers, IDEs, and platforms with next to zero configuration.
- a_e_k 4y agoThe key thing about print debugging for me, that I've never seen a typical debugger handle well, is what I like to think of as "temporal debugging": Taking a program trace from the print debug statements, grepping through it repeatedly to filter down to certain events of interest, looking at the interleaving of those events, and figuring out the order that things happened in to cause it to go off the rails. That sort of thing. (To be fair, time-travel debuggers can start to get at this, but those are pretty uncommon. Traces, as you say, work almost everywhere.) Or better yet, compare the traces between working and non-working runs to see how they differ. I've looked at diffs of traces this way before. (Sometimes I'll first use a small script to renumber pointers in traces by order of appearance.) I've also used this sort of strategy before for debugging rare threading or other non-deterministic issues. Have the shell run the program in a loop, saving each run's trace and results to a different file, go off and get lunch, come back and see if anything failed. Then look to see if any of the runs failed and look for the structural differences between the working and non-working traces. I can't imagine sitting and stepping through in a debugger 100+ times in the hopes that maybe this time, it will be the run that's just different enough to trigger the bug and that the debugger itself won't prevent the issue from manifesting. Not to mention, trying to remember the steps from all the good runs and spotting where the bad run goes bad before you've stepped to far. No thank you. I think people really underestimate print debugging. Debuggers are fast and easy for simple bugs, sure, but there's powerful stuff that you can only really do with printed traces.
- Serow225 4y ago> I can't imagine sitting and stepping through in a debugger 100+ times in the hopes that maybe this time, it will be the run that's just different enough to trigger the bug Isn’t that where things like breakpoint conditions, data breakpoints (“break whenever X value/field changes”), and dependent breakpoints, work pretty dang well? You just set up the appropriate situation and let it run until it breaks
- a_e_k 4y agoThose help in some situations, sure. I'm talking about the non-deterministic things like unusual race conditions, where the problem only manifests rarely. Conditional breakpoints could certainly help you detect when things have broken, but you'll often be well downstream of the root cause by then. Though I suppose tracepoints could help with that. So I'll concede that you could probably do something similar in a powerful enough debugger with sufficient effort. But one thing that I have found helpful in the past has been aggregating the information from the traces across runs. Comparing good with good and bad with bad to classify the commonalities, and then compare good with bad to see how they differ.
- I_AM_A_SMURF 4y agoYeah. Also for any kind of race condition a debugger is usually pretty useless. Also most memory corruption problems. The debugger has a place but so does printf debugging.
- JackFr 4y agoPrint debugging is one of the best ways to learn about buffering and the difference between stdout and stderr.
- Kwpolska 4y ago> I agree you should know how to use a debugger, however will also note that some companies mandate use of a specific IDE (or heavily encourage). The debuggers in most popular IDEs (IntelliJ IDEA/any JetBrains IDE, Visual Studio, VSCode, Eclipse) work the same way. You set breakpoints (typically by clicking somewhere around the line number), step into and out of functions, and look at the memory state. If you learned how debugging works in IDE X, you can easily switch to IDE Y without having to learn much.
- codemonkey-zeta 4y agoThe biggest hurdle for beginners when using built-in IDE debuggers in my experience is the requirement to set up the debug run configuration to properly execute their program. Even though this amounts essentially to "how do you run the program on the command line? Write that in the IDE configurator", newbies don't know how to run the program from the command line (and can't debug any startup errors they might get), so can't properly set up the debugger in their IDE, and revert back to print debugging everything.