Hacker News new | ask | show | jobs
by astrobe_ 2599 days ago
I work with embedded software. About a decade ago, when we switched to a new target processor with a JTAG interface (in-circuit debugging), my boss decided to buy an in-circuit debugger to help development. The target was an high-end (at the time) SoC, so it could run uClinux and we could also have GDB too.

I tried hard to use the hardware debugger because it was rather expensive (this is I think a case of sunken costs fallacy). Problem is, our system is soft real time; stepping in the main program causes the other things connected to the system notice that the main program does not respond, and act upon this.

The hardware debugger was quite capable so we had watchpoints and scripting to avoid this problem, but you had to invest considerable amounts of time to learn to program all that correctly. Amusingly, this was another occasion to make more bugs. Now you need a debugger to debug your debugger scripts...

Moreover, the "interesting" bugs were typically those who happened very rarely (that is, on a scale of days) - bugs typically caused by subtly broken interrupt handlers; to solve that kind of bug in a decent time frame with you would need to run dozens of targets under debuggers to test various hypothesis or to collect data about the bug faster. That's not even possible sometimes.

I also happen to have developed as a hobby various interpreters. The majority were bytecode interpreters. There again debuggers were not that useful, because a generic debugger cannot really decode your bytecode. Typically you do it by hand, or if you are having real troubles, you write a "disassembler" for your bytecode and whatever debugger-like feature you need. Fortunately, the interpreters I was building all had REPLs, which naturally helps a lot with debugging.

So I'm kind of trained not to use debuggers. I learned to observe carefully the system instead, to apply logic to come up with possible causes, and to use print statements (or when it's not even possible, just LEDs) to test hypothesis.

One should keep in mind that debuggers are the last line of defense, just like unit tests that will never prove the absence of bugs. So you'd rather do whatever it takes not to have to use a debugger.

My current point of view is that the best "debugger" is a debugger built inside the program. It provides more accurate features than a generic debugger and because it is built with functions of the program, it helps with testing it too. That's a bit more work but when you do that functionality, debugging and testing support each other.