| I practically live in the debugger. I do use it sometimes to debug a problem, but most of the time I use a debugger to avoid debugging. I use it for coding. I spend a lot of time working with APIs and libraries that are poorly documented and often that I haven't used before. Instead of writing out a bunch of code based on my limited understanding of the docs, and likely with many bugs, what works for me is to just write a few lines of code, until I get to the first API call I'm not sure about or am just curious about. I add a dummy statement like "x = 1" on the next line and set a breakpoint there. Then I start the debugger (which conveniently is also my code editor) and hopefully it hits the breakpoint. Now I get to see what that library call really did, with all the data in front of me. Then I'm ready to write the next few lines of code, with another dummy breakpoint statement after that. Each step along the way, I get to verify if my assumptions are correct. I get to write code with actual data in front of me instead of hoping I understood it correctly. If I'm writing Python code in one of the IntelliJ family of IDEs, I can also hit Alt+Shift+P to open a REPL in the context of my breakpoint. Of course this won't work for every kind of code. If I were writing an OS kernel I might use different techniques. But when the work I'm doing lends itself to coding in the debugger, it saves me a lot of time and makes coding more fun. |
At my last job for example, I frequently would plug the JTAG in to check the instruction pointer and read from the memory-mapped flash on our safety MCU because there was no other way to read data off the device after a crash.
And it was also an asset in quickly testing the programs I wrote for TI's N2HET because I could pause execution after the programs were loaded into the HET instruction ram, use the debugger to configure the variables in the instruction RAM and set the HET executing and watch the output on my oscilloscope. This ability to manipulate memory in the running program is very useful.
I used it very frequently when testing new components on our system buses because I could halt execution and configure DMA transfers and also inject data into system ram. So I could quickly validate my understanding of the reference manuals.
I think both approaches have merits and if someone tells you that one is superior to the other, that says a lot about their level of experience and the types of work they've done.