10 ms·
What a line: > And quite frankly, I don't care. I don't think kernel development should be "easy". I do not condone single-stepping through code to find the bu
by dmitryminkovsky 8y ago
What a line:
> And quite frankly, I don't care. I don't think kernel development should be "easy". I do not condone single-stepping through code to find the bug.
Reminds me of this quote from the introduction to Log4j docs [0]:
> As Brian W. Kernighan and Rob Pike put it in their truly excellent book "The Practice of Programming":
>> As personal choice, we tend not to use debuggers beyond getting a stack trace or the value of a variable or two. One reason is that it is easy to get lost in details of complicated data structures and control flow; we find stepping through a program less productive than thinking harder and adding output statements and self-checking code at critical places. Clicking over statements takes longer than scanning the output of judiciously-placed displays. It takes less time to decide where to put print statements than to single-step to the critical section of code, even assuming we know where that is. More important, debugging statements stay with the program; debugging sessions are transient.
The above quote made me reconsider my intense debugger usage that I had fallen into at the time. On one hand you can't take all your cues from authority, but on the other hand, what K&P said sounded like it might make sense. So I tried using the debugger less and logging more, and over time I think it's made me a better programmer. I think the key statement is:
> we find stepping through a program less productive than thinking harder and adding output statements and self-checking code at critical places.
which Linus also echoes:
> I happen to believe that not having a kernel debugger forces people to think about their problem on a different level than with a debugger. I think that without a debugger, you don't get into that mindset where you know how it behaves, and then you fix it from there. Without a debugger, you tend to think about problems another way. You want to understand things on a different _level_.
[0]: https://logging.apache.org/log4j/2.x/manual/index.html https://logging.apache.org/log4j/2.x/manual/index.html
- ams6110 8y agoI've never really used debuggers routinely. They are a last resort for me. I use print statements and logs for the most part.
- mruts 8y agoI think debuggers are actually a lot less useful than people think. Just by thinking, using a REPL, or putting in print statements you can solve probably 99% of all bugs. Debuggers are useful when you really have no fucking idea what's going on.
- tom_ 8y agoOr instead of putting in print statements, you could use a debugger. You don't even need to know which print statements you need, because when the program is stopped you can look at whatever you like. Thinking is still required, but I don't recommend relying on it, since it's typically what gets you into this whole mess in the first place. At the very least, don't rely on thinking to guess what the computer is doing, when you can use the debugger to find out for certain.
- AnIdiotOnTheNet 8y agoI'd agree generally. I pretty much have only used debuggers when reverse engineering something or when I'm so hopelessly unable to see what the problem could be that I start suspecting the compiler might be at fault. Even when reverse engineering something it's best not to get bogged down in the instruction-by-instruction details and instead try to follow the general program flow and reason about how you would do something if you were in the programmers' shoes.
- magduf 8y agoThis has been my experience as well: I only resort to the debugger when my other avenues have proven fruitless. They can also be useful for Heisenbugs. However, I did have one job working on an embedded device with no console at all, and a JTAG debugger was invaluable there. But I would have preferred to have a console and be able to do printf debugging, as for easier bugs it's just a lot quicker.
- ilikehurdles 8y agoI use a repl with a debugger attached in clojure. Best of both worlds :).
- jshowa3 8y agoThe problem with print statements is that you're now adding unnecessary code to the application that you then have to take out. How many of us have been lazy and just left them in? I know I have. Thus you violate KISS and add unnecessary complexity to code when you could've just used a debugger. As for logs, those are a necessity and should be in every complex program not just because of exceptions, but because of program logic that you implement and want to know where you are, and were, while the program is in use.
- kevin_thibedeau 8y agoIt's not exactly challenging to have prints only show up in debug builds.
- Koshkin 8y agoYeah, but they're still in the code. Tracing is nice when it is a feature built into the language implementation (i.e. the compiler or the interpreter).
- lunchables 8y agoSame, but I always feel like using a debugger has to be a better way to handle that stuff and that I just haven't invested enough time to get the workflow right. Maybe prints and log statements are better.
- tomc1985 8y agoI was the same way until I worked at a place that would not let us merge clearly WIP code. Now, debuggers are life!
- Jorge1o1 8y agoUsing a print statement to display the value of a variable is no different than putting a breakpoint at that line and just reading the state of your program off the locals window
- kevin_thibedeau 8y agoThe latter freezes your program for non-trivial amounts of time which can be problematic in some cases.
- yorwba 8y agoYes, for example setting a breakpoint in your input method engine while it's relaying your keystrokes to the terminal with the debugger tends to go poorly. On the other hand, gdb supports the "commands" command, which allows you to automatically run a script when a specific breakpoint is run. That way, you can do essentially everything you can do by inserting logging statements directly into the code, but without having to restart the process.
- pjmlp 8y agoWith dynamic trace points and scripting there is no freezing.
- jstimpfle 8y agothere are significant differences as discussed elsewhere. Additionally, you can't read globals or other complex computed expressions from the locals window...
- deleted 8y ago[deleted]
- Tcepsa 8y agoI'm a little confused about their apparent implication that they have to single step all the way to the point that they want to inspect. Maybe older debuggers made you do this? But today, breakpoints are useful and seem to be widely supported, so you can run the program at full speed to the point of inspection, and then instead of getting a drive-by snap-shot as you do with a printout, you can do a more in-depth interrogation of the state of the system "Oh, this part of the state has value X as I expected, maybe it's this other part of the state instead--yes, there is something weird over here!" instead of discovering value X in the first run, adjusting your print statement, recompiling, and discovering the unexpected behavior. All that having been said, surely there is still great value in applying a similar amount of consideration as to where to put the breakpoints as you would in determining where to put a print statement! (edit: and also in thinking hard about what new values to inspect if your initial guess is not borne out)
- dmitryminkovsky 8y ago> "Oh, this part of the state has value X as I expected, maybe it's this other part of the state instead--yes, there is something weird over here!" instead of discovering value X in the first run, adjusting your print statement, recompiling, and discovering the unexpected behavior. This is why I love debuggers. Well, the Chrome debugger. But I find that this situation is less common or doesn't happen at all when I'm writing Java with unit tests. It seems like dynamic environments like the browser are more ripe for debugger use as you describe. But then again, I've met some incredible developers who made really great browser UI (ie the RethinkDB UI) who told me they've never used the browser debugger.
- XorNot 8y agoThe real trick is that gdb is scriptable. You don't print debug - you set your breakpoints, add some logic for deciding what you want to output and where, and then run at full speed.
- deleted 8y ago[deleted]
- nitrogen 8y agoI've never found something as nice as Ruby's binding.pry. I've added JRuby to Java projects temporarily just to get the interactive introspection of a REPL.
- epage 8y agoI wholeheartedly agree with K&R. A lot of the hard problems I've debugged have been the interaction of multiple state machines. In these cases I needed to see the forest of interactions rather than the trees of instructions. On top of that, I felt it was faster with getting more information up front (the entire log) rather than identifying what I need to look at, starting the program with debugger attached, setup break points, get more information, and repeat (yes, a lot of my problems required relaunching the process or even rebooting so I could start from a known good state, yay hardware drivers).
- gpm 8y agoI suppose Rob Pike has a R in it, but the R in K&R usually refers to Dennis Ritchie. This should probably be K&P.
- graedus 8y ago> It takes less time to decide where to put print statements than to single-step to the critical section of code, even assuming we know where that is. Stupid question - did their debugger not have breakpoints? Not that that would make using the debugger superior in all cases, but would eliminate time wasted "single stepping to the critical section". I do agree with their overall point.
- danmaz74 8y agoI think it depends a lot on context. On a project with good automated tests, I find that I don't need to use the debugger very often. But, those times when I had to use it, it saved me probably thousands of hours of work - especially when debugging complex software which I didn't write myself.
- hi41 8y agoI admit that I am not a good programmer as many in this thread are. I remember being scared and nervous looking at a large codebade and single stepping through the code. I did not know how else to understand the code. You mention that one needs to think at a different level. Could you offer pointers as to what that level could be. I lost my job as a developer and I am trying to get a developer position. However I am absolutely scared of looking at large codebase and not being able to understand it and later not being productive.
- jerf 8y agoI'm generally not a debugger user, not really out of principle but out of generally just not using one much, but I have two major exceptions: 1. Highly recursive code 2. Understanding a new codebase. It is true you ought to build up a model of what code is doing to work on it properly, but I find trying to just read the code that I'm not familiar with to build that model is often both slower and worse than using a debugger to walk through it. Slower, because I'm sitting on the outside trying to stare in at a dynamic process based on my radically incomplete understanding of its static description and the stored state in my rather meager head (I think my raw ability to hold state in my head is probably a bit below average in the programming domain, as evidenced to me by the behaviors I've developed to compensate and other people's lack of need for them). Worse, because when simply reading code it's easy to miss the "validate_input(input)" call that in fact turns out to invoke a multi-thousand line subsystem that doesn't just validate the input, but also statefully mutates it based on all kinds of things and is actually 60% of the system despite its seemingly innocuous name. Stepping through can fix both problems much more quickly, and I'm not being paid to "not use a debugger". I don't disagree that pervasive, continuous use of a debugger can afford bad habits, but the best answer is to simply not develop those bad habits, and then still use it when it is helpful... because there are days when it is very very helpful. (Highly recursive code is an exception because Ye Olde Printe Statementse really break down at that point, and even if you make them work it can still be a lot easier to understand it from the inside than the outside, after the fact. I don't just mean "recursively folding on a list", I mean code that does things like walk heterogeneous trees for a DOM tree or a compiler AST and does a whole bunch of inter-related recursive stuff. Sometime you just have to admit your brainstack has overflowed and call in the tools. Best to avoid writing that code at all if you can, of course, but there's times when it is not avoidable.... because that's where the superpowers come from: https://steve-yegge.blogspot.com/2007/06/rich-programmer-food.html https://steve-yegge.blogspot.com/2007/06/rich-programmer-foo...)
- jandrese 8y agoPersonally I find debuggers invaluable when you're handed some huge chunk of code that someone else wrote and asked to fix it quickly. The "stop and think about it" only works when you already know the code in and out. If you're having to discover how it works to fix problems with it being able to single step through the flow is invaluable. Once you grok the code you can dial back the debugger use, but by that point you've fixed the bugs and moved on to the next project.