Hacker News new | ask | show | jobs
by bluGill 585 days ago
Depends on the developer. in the Practice of Programming https://en.m.wikipedia.org/wiki/The_Practice_of_Programming by Brian W. Kernighan and Rob Pike they say they use debuggers only to get a stack trace from a core dump and use printf for everything else. You can disagree but those are known very good programmers.
2 comments

But what source code debuggers did they have available?

Other than gdb, I can't name any Unix C source code debuggers. I believe they were working on Unix before GDB was created (wikipedia says gdb was created in 1986 - https://en.wikipedia.org/wiki/Gdb).

Plan 9 has acid, but from the man page and english manual, the debugger is closer to cli/tui than gui.

see https://9fans.github.io/plan9port/man/man1/acid.html and https://plan9.io/sys/doc/acid.html

Looks like there was an adb in 1979 which is supposedly the successor to db.

https://en.wikipedia.org/wiki/Advanced_Debugger

What if the program doesn’t crash? It just black-boxes the data incorrectly? I can find that error infinitely faster with a debugger.
Printf debugging excels on environments where there's already good logging. Here I just need to pinpoint where in my logs things have already gone wrong and work my way backwards a bit.

You could do the same with a debugger setting up a breakpoint, but the logs can better surface key application-level decisions made in the process to get to the current bad state.

On a debugger I need to wind back on all functions, which it might get awful as some of them might be likely correct library calls that you need to skip over when going back in time, but that will take a huge portion of the functions called before the breakpoint. I don't think it's impossible to do with a debugger, but logging sort of bypasses the process of telling the debugger what's relevant so it can hide the rest, and it might already be in your codebase, but there's no equivalent annotations already there in the code to help the debugger understand what's important.

To me printf helps surfacing the relevant application-level process to get to a broken state, and debuggers help understand hairy situations where things have gone wrong at a lower level, say missing fields or memory corruption, but these days with safer languages lower level issues should be way less frequent.

---

On a side-note, it doesn't help debuggers that going back in time was really hard with variable-length instructions. I might be wrong here, but it took a while until `rr` came out.

I do think that complexities like that resulted in spending too much time dealing with hairy details instead of improving the UI for debugging.

I appreciate your candor.

I really value debuggers. I have spent probably half my career solving problems that weren’t possible to solve with a debugger. When I can fall back on it, it helps me personally quite a bit.

I find them amazing, it's just that printf is unreasonably good given how cheap it is.

If I had the symbols, metadata, powerful debugger engine and a polished UI, I'll take that over printf everyday, but in the average situation printf is just too strong when fighting in mud.

Why not both? For any sufficiently complex app you will have some form of logging either way, and then you can further pinpoint the issue with a debugger.

Also, debuggers can do live evaluation of expressions, or do stuff like conditional breakpoints, or they can just simply add additional logs themselves. They are a very powerful utility.

Your existing logs will tell you roughly where and you just insert some more log lines to check the state of the data.

Depends how fast your build/run cycle is and how many different prcocesses/threads whether a debugger will be faster/easier but a lot of it just comes down to preference. Most time spent debugging for me at least is spent thinking about the probable cause then choosing what state to look at.

Logs are gold. Parsing logs can be very exhausting.
They use printf. Which they claim is faster.
Faster than pressing F9 (to set a breakpoint on the current line) and then F5 (to start into the debugger)?

Printf-debugging has its uses, but they are very niche (for instance when you don't have access to a properly integrated debugger). Logging on the other hand is useful, but logs are only one small piece of the puzzle in the overall debugging workflow - usually only for debugging problems that slipped into production and when your code runs on a server (as opposed to a user machine).

It’s very interesting. I’ve tried to observe myself. It seems that if I can see a breakpoint somewhere and then examine state and then see what the problem is, a debugger is great.

If, however, it’s something where I need to examine state at multiple times in the execution, I lose track in my mind of the state I’ve seen before. This is where print debugging shines: I can see how state evolved over time and spot trends.

I'm not against printf at all, my lifetime commit history is evidence of that. Do you also think that in the case of a coredump not existing, that printf is faster? Sincere question. I'm having an internal argument with myself about it at the moment and some outside perspective would be most welcome.
Most of my time with printf degugging is spent trying to reason about the code not compiling.

though you should note that I'm repeating their claims. What I think is hidden.

printf isn't faster if you want to single step through code to find math precision errors.

I've had to do that on a embedded system that didn't support debugging. It was hell.

I’ve always wondered why embedded devs make less than “JavaScript-FOTM” devs.