15 ms·
What a good debugger can do
- choletentent 4y agoThis piece from Linus on why he doesn't like debuggers resonates with me [1], although I confess I use Python pdb quite often. [1] https://lkml.org/lkml/2000/9/6/65 https://lkml.org/lkml/2000/9/6/65
- sokoloff 4y agoI really enjoyed this thought in that mail: “Tough. There are two kinds of reactions to that [time lost from a bug you introduced in kernel dev]: you start being careful, or you start whining about a kernel debugger.”
- matheusmoreira 4y agoHe also reminds people why everyone pulls from torvalds/linux to this day: > People think I'm a nice guy, and the fact is that I'm a scheming, conniving bastard who doesn't care for any hurt feelings or lost hours of work if it just results in what I consider to be a better system.
- heinrichhartman 4y agoContrasting perspective from John Carmack [1] who drops into a debugger all the time to explore state, understand program behavior, debug things, etc. Looks like there is no universal golden path. Differing environments make different approaches effective. [1] https://www.youtube.com/watch?v=tzr7hRXcwkw https://www.youtube.com/watch?v=tzr7hRXcwkw
- jcranmer 4y agoThat sort of argument is somewhat defensible in a context like the kernel, where when things go haywire, you can't really expect there to be enough sanity to have a debugger work. But very little code runs in such a context, and it turns out that a well-written debugger has incredible features. Also, Linus is writing this 22 and a half years ago, where the capabilities of debuggers were... far, far less. Time-travelling debuggers is really a game changer, just having the ability to travel back in time to figure out who set the value that causes the code to crash. Hot reload is also a wonderful thing (unfortunately, the fragmentation of tooling in Linux makes getting this working properly very difficult).
- eschneider 4y agoLots of (most?) real-time and embedded code run in a state where suspending/resuming really doesn't work in any useful fashion, so it's logging, and minimal logging at that to figure out what's going wrong in-situ. That said, much benefit is gained by writing the complicated bits in such a way that they can be tested/debugged/examined independently on a host system.
- realo 4y agoI'm with you there! Be happy if you can flash a led... happier if you have two speeds... and Nirvana if it is a multi-color led. Intense jealousy of your colleagues who have TWO leds on their boards!
- nuancebydefault 4y agoHmmm I have 20+ years of embedded sw programming experience and can tell you the reason that embedded software is oftentimes not easily debugged using a debugger, is the crappyness of the debugger solution (debug probe, its firmware and its eco system). Also, high end embedded ICs often contain a serious amount if silicon bugs. The fact that it needs to run real-time, is mostly not in the way of the debugging process. In other words, embedded processors and their eco systems tend to be sub-par in terms of developer friendlyness. Addendum SHARC ADSP anomaly list https://www.analog.com/media/en/dsp-documentation/integrated-circuit-anomalies/adsp-21467_21469-sharc-anomaly.pdf https://www.analog.com/media/en/dsp-documentation/integrated...
- deckard1 4y ago> Time-travelling debuggers is really a game changer Core dumps have existed forever. They give you a stack trace and register values at the time of crash. Even better, you don't need a debugger running at the time of crash and you can dig into dumps sent from nontechnical users. Sure, Bret Victor's demo was cool. But time travel debugging is so completely oversold at this point that I can't take anyone seriously that mentions it.
- jcranmer 4y ago
- carapace 4y agoSeems as good a hook as any to hang this rant... > a good debugger supports different kinds of breakpoints, offers rich data visualization capabilities, has a REPL for executing expressions, can show the dependencies between threads and control their execution, pick up changes in the source code and apply them without restarting the program, can step through the code backward and rewind the program state to any point in history, and even record the entire program execution and visualize control flow and data flow history. TL;DR: That's fantastic! But if you need any of it you're already "doing it wrong". Context: I've recently been using a compiler for a C-like language that targets a simple 64-bit VM, the point being there's no debugger for the stack (the VM is written in Rust; I could put a debugger on that and just deal with the extra level of abstraction using e.g. features like those described above.) So how do you cope? Design simple and robust systems that can be understood in action easily via printf/log. Use tried-and-true off-the-shelf components (including algorithms and datastructures.) Write in small increments, compile often, never proceed without complete confidence in your understanding of the system. When the inevitable bugs appear, and they can't be discovered through just thought or a rereading of the code, then you bisect: often literally (LoC) but also conceptually. Solve the puzzle and eliminate the places where puzzles can hide in the first place. I quite literally see how a having a debugger would lead to worse code. (Even if you don't use it.) This isn't news btw: > Everyone knows that debugging is twice as hard as writing a program in the first place. So if you’re as clever as you can be when you write it, how will you ever debug it? -- Brian Kernighan, 1974 (The feeling is different: like instead of a wild adventure, programming this way feels like gardening in an orderly and well-kept garden.)
- cgh 4y agoIn the real world, programmers are brought into projects with literally millions of lines of code that have been developed over years or decades by tens or hundreds of programmers. They are under intense time pressure to fix bugs that they likely didn’t create. This is normal and debuggers are invaluable. No offence, but what you’re describing is a lovely ideal that only exists if you work mostly alone or on small things.
- carapace 4y ago
- Yoofie 4y agoA whole world of creative opportunities open up when the toolchain and related debugging tools don't suck. Check out this wild video[1] of someone modifying and debugging a game in real time. [1]: https://youtu.be/72y2EC5fkcE https://youtu.be/72y2EC5fkcE
- WirelessGigabit 4y agoI am a huge proponent of debuggers. Being able to look at state step by step without having to stop, add log statements, recompile and go back are too slow (for me). What concerns me more is that is that I end up working with contractors with 5+ years who don't know how to set up a debugger for the code they are working on. And that concerns me. It's not OR logging OR debugging. It's both. You use the best tool for the job.
- ska 4y agoIt's definitely both. Ideally the debugger is never your first resort. An extremely common failure mode for less experienced developers is messing about in a debugger all afternoon for a problem that should be solvable in 5 minutes. It's a very slow way to learn.
- fluoridation 4y agoWeird, I've never run across that. I have wasted a lot of time rebuilding and retesting figuring out where to put a print statement and then figuring out what and how to print it, where a debugger would have let me turn breakpoints on or off and watch different variables in the same run, all without touching the code. I don't think I've ever thought "gee, this debugger sure is getting in my way! I wish I could do printf-debugging instead."
- euiq 4y agoI assume the parent comment is talking about "thinking" (not that I have any personal experience with that).
- ska 4y agoThe world isn't printf debugging or debugger only. Some things are really amenable to the debugger, especially simple bugs. Really especially ones that should have been caught by static analysis anyway but that's a separate issue. The issue is that firing up a debugger can easily become a fishing expedition. If you don't understand the system behavior and you don't know where the real problem is, you can end up manually stepping through many many layers of a system trying to see what it's doing. Add asynchonicity and this can take hours before you get to the 20 lines of logic that is the actual problem. Ideally you have better logging and introspection, so the problem is caught in a way that leads you to those 20 lines immediately. And of course design can make a huge difference in how understandable and localizable things are. The problem a lot of inexperienced developers run into is if they are used to having a featureful debugger available it can become the only tool they have in their toolbox, and they are rewarded by how quickly it helps them fix the kind of mistakes their inexperience leads them to making a lot of. When they run into a real issue, they can be hitting "step" for hours.... The other pernicious side of this particular coin is that it can lead to localized understanding of the problem and make it really easy to apply a localized solution. With inexperienced people this can quickly lead to band-aid solutions all over the place. With any luck someone more experienced is looking it over and pointing out they should go after the actual problems, but left unchecked it can make a real mess.
- sebastianconcpt 4y agoa good debugger supports different kinds of breakpoints, offers rich data visualization capabilities, has a REPL for executing expressions, can show the dependencies between threads and control their execution, can pick up changes in the source code and apply them without restarting the program, can step through the code backward and rewind the program state to any point in history, and can even record the entire program execution and visualize control flow and data flow history. I should mention that the perfect debugger doesn’t exist. People pretends Smalltalk doesn't exist?
- aidenn0 4y agoIs there a ST implementation with a time-traveling debugger? That's probably the one feature I miss when using sbcl/slime.
- igouy 4y agoDepends what functionality you think "a time-traveling debugger" must provide, Smalltalk implementations usually provide something like this: https://cuis-smalltalk.github.io/TheCuisBook/The-Debugger.html https://cuis-smalltalk.github.io/TheCuisBook/The-Debugger.ht...
- aidenn0 4y agoTo qualify as "time-travelling" You should at a minimum be able to step and run backwards and inspect the values of variables at a previous point in time. Ideally all debug features (breakpoints, watchpoints, tracepoints &c.) will work running both forwards and backwards. To meet the standard of the "perfect debugger" from the TFA intro, I would say you should be able to run backwards, modify a function, and run forwards again. I'm not aware of any debuggers that let you do this.
- leni536 4y ago> Ideally all debug features (breakpoints, watchpoints, tracepoints &c.) will work running both forwards and backwards. Executing arbitrary code in the program's context is also a regular debug feature, but I don't think many reversible debuggers allow this.
- Decabytes 4y agoI've always been curious about Debuggers. How do they work? How do they connect to a program and step through it. Why can't more compiled languages integrate debuggers inside of them so that you can debug the program without using a separate tool? And why can't we create interfaces to debuggers so that other text editors can integrate with them, much like how we do we LSPs? *EDIT* Thanks for all the responses! I've now heard from multiple sources that debugging on Linux is unpleasant, and it seems like the whole process is challenging regardless of the platform.
- ghosty141 4y agoAbout the latter, there is an LSP equivalent called DAP (debug adapter protocol).
- not2b 4y agoOn Linux or BSD, the ptrace system call allows one process to take control of another process; it can then observe and control the other process. Breakpoints are inserted by replacing an instruction with a special instruction that traps; the debugger can then take control. Watchpoints (the article calls them data breakpoints) are often implemented by making the containing page read-only, so that a write access traps (this means that there's overhead from other writes to the same page, the debugger has to just resume execution silently for those). A checkpoint can be implemented by forking the process and freezing the fork, so execution can go back to that point.
- jcranmer 4y ago> How do they work? Painfully. If you're on Linux, you get to use a mixture of poorly-documented (e.g., ptrace) and undocumented (e.g., r_debug) features to figure out the state of the program. Combine this with the debugging symbols provided by the compiler (DWARF), which is actually a complicated state machine to try to encode sufficient details of the source language, and careful reading of the specification makes you throw it out the window and just rely on doing a well enough job to keep compatibility with gdb. > Why can't more compiled languages integrate debuggers inside of them so that you can debug the program without using a separate tool? Because it's really painful to make debugging work properly. At least in the Unix world, the norm is for all of these tools to be developed as separate projects, and the interfaces that the operating system and the standard library and the linker and the compiler and the debugger and the IDE all use to talk to each other are not well-defined enough to make things work well. > And why can't we create interfaces to debuggers so that other text editors can integrate with them, much like how we do we LSPs? LSPs have the advantage of needing to communicate relatively little information. At its core, you need to communicate syntax highlighting, autocomplete, typing, and cross-referencing. You can build some fancier stuff on top of that information, but it's easily stuffed in a single box. Debuggers need to do more things. Fundamentally, they need to be able to precisely correlate the state of a generated build artifact to the original source code of the program. This includes obviously things like knowing what line a given code address refers to (this is an M-N mapping), or what value lives in a given register or stack location (again an M-N mapping). But you also need to be able to understand the ABI of the source level data. This means you can't just box it as "describe language details to me", you also have to have the tools that know how to map language details to binary details. And that's a combinatorial explosion problem.
- Lichtso 4y agoOne style that haven't seen discussed is a hybrid / mixture of in-code (e.g. printf trace-logs) and out-of-code (using external tools like an attached debugger) debugging. What I do is I encode conditional breakpoints in the source code, (compile and) run the program with a debugger attached. The nice thing is you can have complex conditions using all kinds of functions from your surrounding code and you can have them permanently, even check them into the VCS. It is kind of like placing asserts which don't panic but trap into the debugger and they can be globally enabled / disabled.
- ghosty141 4y agoConditional breakpoints are supported for most dynamic languages. With static ones like c++ your way is the only practical way I believe
- fluoridation 4y agoVisual Studio supports conditional and printing breakpoints for both C and C++. I tend to use them rarely because they really hurt performance, though. I only use them if I need to be able to turn them on and off at will, which hardcoded __debugbreak()s don't allow, obviously.
- mark_undoio 4y agoI helped implement fast conditional breakpoints in UDB (time travel debugger for Linux) - https://www.youtube.com/watch?v=gcHcGeeJHSA https://www.youtube.com/watch?v=gcHcGeeJHSA We used GDB's conditional breakpoint bytecode https://sourceware.org/gdb/onlinedocs/gdb/General-Bytecode-Design.html https://sourceware.org/gdb/onlinedocs/gdb/General-Bytecode-D... to get a speedup in the thousands of times vs plain conditional breakpoints. That works for us because we've got in-process agent code that can evaluate the breakpoint condition without trapping. It should be possible to do this in other debuggers with a bit of work, though we have the advantage of in-process virtualisation to help hide this computation from the process.
- thewebcount 4y ago
- yellowjobby 4y ago> We can snapshot the program whenever something non-deterministic happens (syscall, I/O, etc) and then we just reconstruct the program state at any moment by rewinding it to the nearest snapshot and executing the code from there. This is basically what UDB, WinDBG and rr do. QEMU does this too. This plus its GDB stub means one can time-travel-debug pretty much anything on any emulated architecture. https://www.qemu.org/docs/master/system/replay.html https://www.qemu.org/docs/master/system/replay.html
- _gabe_ 4y ago> I should mention that the perfect debugger doesn’t exist It may not exist, but this demo has got to be the closest thing to the perfect debugger I've ever seen: https://youtu.be/72y2EC5fkcE https://youtu.be/72y2EC5fkcE
- kaba0 4y agoWow, that’s absolutely insanely cool!
- aantix 4y agoI think the visualizations are highly underutilized. There's so much that can derived from the code itself and the runtime profile. That's why I'm creating the next generation debugger for Rails. https://callstacking.com/ https://callstacking.com/
- kubb 4y agoI use the debugger occasionally, when the human factor creeps in and I inadvertently make a programming error. The downside of debugging is obvious: it's not enabled in your production programs (although it could be). Logging OTOH is always on, and it has to be good enough to let you figure out what happened on a remote machine, in a program whose state you can't recreate anymore. This obviously makes it good enough for debugging programs running locally, and makes reaching for a debugger a rare occurrence. GUIs for debuggers of course lag behind, so you need to refresh your memory of the step, step over and breakpoint instructions, etc. on every one of these rare occasions. And then they don't always work. Printing more complex data structures is often an unholy mess of pointers to strings and private class fields. Evaluating expressions will end up failing or crashing your program. The symbol you're trying to break on doesn't exist? But why? This makes debuggers unusable for a mediocre developer.
- jpmonettas 4y agoThis is another example, a tracing time travel debugger for Clojure https://github.com/jpmonettas/flow-storm-debugger https://github.com/jpmonettas/flow-storm-debugger Supports a bunch of stuff described there and more.
- frou_dh 4y agoIf someone's preferred language/framework/environment doesn't have a good debugger, or if they simply don't know how to set it up, some percentage of them will start insisting that they don't even want one anyway. This is the basic Sour Grapes concept.
- oneshtein 4y agoDebugger is a tool, not a goal. I can reach a GOAL without debugger, using my software development skills only. I prefer to invest into quality of code, write more comments and documentation, perform refactoring, delete unused code, write test case to reproduce the bug, add more command line parameters, write better error messages with more data, and so on, than to invest time into a debugger. I'm the Software Developer, not a Software Debugger.
- Jorengarenar 4y ago>When people say “debuggers are useless and using logging and unit-tests is much better,” Who? Who does say that? Freshman students who barely started coding? >I suspect many of them think that debuggers can only put breakpoints on certain lines, step-step-step through the code, and check variable values. That alone provides enough value to know debuggers are useful.
- maleldil 4y ago> Who? Who does say that? Freshman students who barely started coding? Example from this thread: https://news.ycombinator.com/item?id=35098434 https://news.ycombinator.com/item?id=35098434
- justeleblanc 4y agoDo we know if that person is a freshman student who barely started coding?
- bornfreddy 4y agoThere are many other experienced devs (me included) who simply don't see debuggers worth the effort in most cases. There are exceptions and every competent dev should know how to use one, but to me it is like using crutches - I run faster and better without them. I did use debuggers at the beginning though, a lot too. Then I learned to think about problems and to simplify design of the code, making debuggers much less useful.
- maleldil 4y agoI find it useful to run pdb when my program throws an exception. You can run your program with `python -m pdb -cc file.py args`, and it will leave you in a prompt when there's an exception or a breakpoint (eg the `breakpoint` statement). From there, you can evaluate expressions using local variables.
- aflag 4y agoLinus Torvalds famously dislike them: https://lwn.net/2000/0914/a/lt-debugger.php3 https://lwn.net/2000/0914/a/lt-debugger.php3
- zwieback 4y agoI'm a debugger lover and Visual Studio's is pretty great but GDB is also awesome. However, when debugging embedded systems with a good trace probe it's another whole world, using on-chip trace capabilities and being able to break on things like register or peripheral access makes it even more exciting. And expensive, unfortunately, since it's such a niche thing.
- hnthrowaway0315 4y agoJust curious how does one build the tools you talked about? I'm referencing both hw and sw: hw part I guess is "on chip trace capabilities" and sw is "break on registers or peripheral access". I'm not an embedded dev neither am I a debugger developer but I'm playing with toy OS dev so just curious.
- zwieback 4y agoThe setup I'm most familiar with is ARM-based microcontrollers, here's an overview from their docs: https://developer.arm.com/documentation/ihi0014/q/Introduction/About-Embedded-Trace-Macrocells/The-debug-environment https://developer.arm.com/documentation/ihi0014/q/Introducti... and the debugger from Keil (used to be independent, now part of ARM): https://www2.keil.com/mdk5/debug https://www2.keil.com/mdk5/debug
- hnthrowaway0315 4y agoAh thanks, I thought they are yet to be made.
- RcouF1uZ4gsC 4y agoI have mostly found the people who dismissed debuggers tended to be more Unix/Linux people, probably because raw gdb is such a huge pain to use. Windows developers and Visual Studio developers where the debugging experience is so easy, tend to sing the praises of debuggers. I wonder if it a bit of sour grape for the Unix/Linux crowd?
- TheRealDunkirk 4y agoAs much of a Linux zealot as I am, you make a valid point. In college, I had a TA help me debug a C program on a VAX, and he blew through finding the problem using its native debugger, and wouldn't explain what he did. (I had an O where a 0 should have been. Or vice versa. It was a worse problem back in the days of actual terminals. He found it in literally 30 seconds after I had been bashing my head on the printout for a couple hours.) Anyway, it took me probably 10 years of professional coding before I discovered gdb, and then realized what that TA had done. All at once, I realized how far you could get without an actual debugger, and also why he never bothered to try to explain it to me. I wasn't ready. Not by a long shot. Seeing the right-click options on breakpoints in Visual Studio was... revelatory.
- pjmlp 4y agoDepends on the UNIX, Solaris, HP-UX and NeXT/macOS are all UNIXes with good debugging experience. Naturally none of them have had raw gdb, rather modern graphical debuggers.
- matheusmoreira 4y agoI found GDB to have a steep learning curve, even stepping through code was hard at first. Now I simply cannot work without it anymore. I have GDB scripts for visualizing all my data structures now. GDB script is a painful little language but it just changed everything for me.
- AcerbicZero 4y agoHonestly if most debuggers did what the author suggests in the first paragraph, I'd use them 10x more. Other than Pry for ruby I've not found many to debugger tools that let me drop into code, run parts of it, examine variables etc, without needing a 4 year degree in using the debugger itself.
- BiteCode_dev 4y agoPdb comes to mind.
- hobs 4y agoPycharm/Intellij stuff does everything you mention in a fairly simple GUI that doesn't make you understand how to set conditional variables, but encourages you to realize you want to
- alexdig 4y agodo you know if it's possible to step back in pycharm/intellij? the article mentions some debuggers having this ability, but i never saw an option in pycharm. learning how to undo my last step would save so much time. right now, i have to anticipate a risky step and run that line in the debugger console.
- hobs 4y agoUnfortunately I dont think there's any time traveling debugger - you can pretty easily go up and down the stack to see where the caller did x and write something in the console to do y, or you can set conditionals that would always trip when you are about to do something risky, but not go back in time.
- greglaw99 4y agoThis https://plugins.jetbrains.com/plugin/14767-time-travel-debug-for-java https://plugins.jetbrains.com/plugin/14767-time-travel-debug... gives time travel debugging for IntelliJ. (Disclaimer, I work for Undo.) I don't think there is a solution for PyCharm.
- armchairhacker 4y agoThis is what a good debugger can do: https://twitter.com/yiningkarlli/status/1628612150041382912 https://twitter.com/yiningkarlli/status/1628612150041382912 (Tomorrow Corporation)
- euiq 4y agoGreat demo! The article also has a link to it.
- hnthrowaway0328 4y agoWow I'm just 5 mins into the video and this looks ridiculously powerful. This is essentially an integrated development environment for game development with everything every programmer dreams about! How do I learn to make such tools? From what I heard everything in the video is built in-house including the language and compiler. Although I understand many game studios do similar stuffs this is by far the most impressive I heard about.
- MikeSchurman 4y agoThis was on hacker news a few days ago but there wasn't much interest, which is surprising. Setting a data breakpoint, then rewinding time, then fixing the error in code (while game is running), hot-reloading code and continuing the run with it fixed. All from a recording of a panic dump from another user. This is next level stuff. Extremely impressive.
- invalidname 4y agoI like this article. There are more such tips like that in this series: https://www.youtube.com/watch?v=A919j_5qE0k https://www.youtube.com/watch?v=A919j_5qE0k
- javier_e06 4y agoJust yesterday I was trying to dive into a container running some c program and I took a look at gdb... again, for the n time.. and the whole ordeal of the gdbserver and gdb as a client and the symbol table yadda yadda yadda I just rebuild the program with some printfs displaying data, filename and line number and re ran it. Done. gdb is stifling.
- mark_undoio 4y agoHave you tried using a Time Travel Debugger to record the process and then just debug the recording outside? You can use rr or LiveRecorder (commercial product, which I work on) to generate the recording non-interactively then debug it "locally". Avoids the need to set up a client/server configuration, so long as you don't need to modify variable values at runtime, etc.
- sigjuice 4y agoContainers are the real ordeal and not just here.
- rr808 4y agoVisual Studio C++ did this in the 90s. I never understood why Unix devs preferred emacs/vim back then.
- pjmlp 4y agoI prefered XEmacs, because it was the only thing that could improve my experience versus Borland Turbo Pascal and C++ IDEs, and it was much better than plain Emacs or VI (vim was years away to materialize). Nowadays only if I am on bare bones installation, I reach out for emacs or vim, on that order.
- avg_dev 4y agoThanks very much for posting this article. I found it very intriguing. I read it carefully but I didn’t visit all the links or watch all of the in-line videos. I would say that for the most part I am a printf-style debugger. I remember reading some years ago (on HN, I believe) about time travel debugging in - I believe - C# and I was really impressed but I don’t code in C# so it soon left my mind. I have a deep appreciation for mastering one’s toolset. I can’t think of the number of times that I learned something new about a tool (language, editor, shell, browser, whatever) that I use daily that changes my workflow - it has happened so many times. And as with all things code, sometimes new features are added. I am going to try to make a point to re-read this article later and to visit each link and glean what I can. I mostly code in Go. I wonder, does anybody know how much of this stuff might be supported there?
- mark_undoio 4y agoFor time travel debugging in Go: The Delve debugger for Go supports debugging rr traces: https://github.com/go-delve/delve/blob/master/Documentation/usage/dlv_replay.md https://github.com/go-delve/delve/blob/master/Documentation/... Undo (who I work for) maintain a fork that debugs our LiveRecorder recordings: https://docs.undo.io/GoDelve.html https://docs.undo.io/GoDelve.html Either rr (https://rr-project.org/ https://rr-project.org/) or our UDB debugger (https://undo.io/solutions/products/udb/ https://undo.io/solutions/products/udb/) can do some time travel debugging of Go programs via GDB's built-in support for Go. I believe its weakness is in support for goroutines, since they don't map well onto its idea of how programs run.
- pcdevils 4y agoThe same tools don't work on windows either. Delve works well as a remote debugger against go on windows server though. Another fun one is go won't create dumps on panic on windows when GOTRACEBACK=crash is set.
- intelVISA 4y agoNot tried it unfortunately but there's a travel-time debugger for C(++) somewhere.
- msoad 4y agoUnfortunately debug-ability usually stops when you have a distributed system in which each part of the system is playing a different song. I wish my job was working on a program that I could run on a single machine. Then I'll look into debuggers. For now I'm `print`ing and hopelessly looking into service logs in DataDog :(
- layer8 4y agoIt’s a good reason to not unnecessarily distribute your system.
- jayd16 4y agoWould certainly be nice to see some of these PAAS offer a distributed debugger that could track RPCs and breakpoint across machines in the cloud. It seems feasible to "step into" a remote method assuming the request IDs were integrated.
- pjmlp 4y agoApplication Insights on Azure, goes a big deal into that direction. https://learn.microsoft.com/en-us/azure/azure-monitor/app/app-map?tabs=net https://learn.microsoft.com/en-us/azure/azure-monitor/app/ap... Or Java Flight Recorder, https://developers.redhat.com/blog/2021/01/25/introduction-to-containerjfr-jdk-flight-recorder-for-containers#event_templates_in_cryostat https://developers.redhat.com/blog/2021/01/25/introduction-t...
- pjmlp 4y agoThankfully there are things like flight recorder and application insights that marry distributed computing monitoring with debuggers.
- xkriva11 4y agoI'm missing a few other items on this list that I use daily in Pharo - being able to open the debugger directly from the program. What the "debugger" command does in JavaScript. Conditional breakpoints are easier to work with if they can be directly included in the source code - be able to open another debugger on top of the code I see in the debugger. I'm doing the stepping, I'm at a certain point in the method, and I can simply mark the part of the method code that has already been executed or is yet to be executed and start stepping it with the next debugger. This is especially useful for code without side effects. Then I can continue stepping the original method. - be able to have multiple debuggers open and compare their status - to have more freedom in the visualization of values and objects. Having them open in other windows independent of the original debugger, being able to interact with them using code (which can be debugged independently) - be able to save the state of the application and debuggers so that for very hard-to-reproduce errors, I can easily recover the hard-to-retrieve state and experiment with it repeatedly without worrying that I won't get the state again right away
- melvinroest 4y ago> Conditional breakpoints are easier to work with if they can be directly included in the source code The following code (probably, haven't tested it) allows to create a conditional breakpoint only when a certain method is called by tracing down the call stack debuggerIsInMethod: aMethodName ctx := GRPlatform current thisContext. "grab callstack" [ctx isNotNil] whileTrue: [ (aMethodName asSymbol = ctx method selector) ifTrue: [ ^ true ]. ctx := ctx sender ] ]. ^ false So in another method you can send (call the method) that's deeper in the call stack by doing: someMethod "do work" debuggerIsInYourMethod: 'aMethodHigherUpTheCallStack' ifTrue: [ 1 halt ]. "do more work" Use case: Suppose someMethod is being sent/called from everywhere, but you only want to debug it when aMethodHigherUpTheCallStack is sent/called. With this conditional breakpoint (in code), you can :)
- roca 4y agoMost record-and-replay debuggers let you store the recording to debug as many times as you want. Pernosco (which builds on rr) has some really powerful state-recording and state-sharing UI for long-term and collaborative debugging. https://pernos.co/about/notebook/ https://pernos.co/about/notebook/
- turtledragonfly 4y agoI use GDB almost daily, and used Visual Studio pretty deeply for many years (and still a little bit, nowadays), but I must say I am still a "printf debugging" aficionado (or better: real logging). I like many of the features that debuggers can provide, and I think this is a good article to set aspirational goals for what is possible. But my lived experience has generally been that it's a buggy, fuzzy, moving target in terms of overall user experience. GDB, bless its heart, is still somewhat a pile-of-bugs itself. I frequently have it crash, or otherwise get into a "so confused it needs to be restarted" state. Visual Studio is much more stable, though less powerful, too — less scriptable, at least. Perhaps some day, debugger tech^H^H^H^H UX will advance to the point where it really delivers on its promises consistently and solidly. But after 20+ years in software, I am not holding my breath (: There are some situations where a debugger is just the thing you want (eg: hardware breakpoints can be a life-saver), but I find that's more the exception than the rule, at least in the corners of the software world I've worked in. Compare the above with logging: It is simple and trustworthy. As you get good at designing a solid logging system, and interpreting the results, your life just gets better and better. If you get good at using a debugger, you can still be hit with gnarly weird behaviors, debugger apoplexy, optimized-out-code wackiness, etc. that are hard to control or predict. Anyway, "debugger vs. logging" are often presented as some sort of either/or choice, and in some sense it is (you only have X time to spend; where would you like to spend it?), but in many senses it is not; both have their strengths. I just find that the cost/benefit for me has generally favored logging and testing, over the years.
- RMPR 4y ago20+ years is... a lot. I do agree with the sentiment though. At first I was printf debugging because didn't know better. Then discovered debuggers and my mind was blown. But when I reached the point where I hit bugs that would magically disappear when running the program through a debugger, I finally understood that there's value in becoming good at both debugging styles.
- macjohnmcc 4y agoDebugging issues with multithreaded code can be difficult because you could be looking at race condition that only happens when the code is running at full speed and debugging pausing one or all threads could give you an different experience than the real world.
- albertzeyer 4y agoIt's sad that Python does not really support some of these debugging methods. E.g. you cannot really watch variable changes. There are some workarounds, like writing a custom __setattr__ or __setattribute__ in case of an object, or checking all STORE_* operations. https://youtrack.jetbrains.com/issue/PY-30387 https://youtrack.jetbrains.com/issue/PY-30387 https://github.com/gaogaotiantian/watchpoints https://github.com/gaogaotiantian/watchpoints Reverse debugging is also sth I would like to have, and there are a few projects to support this, but it's not really well supported in standard CPython. https://foss.heptapod.net/pypy/revdb https://foss.heptapod.net/pypy/revdb https://pytrace.com/ https://pytrace.com/
- crabbone 4y agoPython debugger is really sad for many more reasons: 1. Cannot interrupt a running program to get debugger prompt, you have to code that functionality in yourself. 2. Cannot deal with threads or multiple child processes because it gets confused by where its output should go, and so it appears to be stuck, prompt doesn't show up, or input isn't being accepted. 3. If someone writes an overly general except, debugger won't ever be called because in order to be called it relies on exceptions. 4. Debugger cannot evaluate comprehensions correctly due to scoping issues (not as much of a debugger fault as much of the language fault). 5. Debugger cannot consistently modify variables inside the function call. Depending on circumstances if you execute an assignment statement in debugger, the value may or may not be set to the variable in current stack frame. 6. Debugger doesn't step into iterator implementation (iirc, I might be confusing with tracing).
- donadigo 4y agoThe article provides a pretty good overview of the landscape of debuggers out there. I find myself using printf debugging whenever something is a dynamically evolving state and I need to monitor just the relevant bits of it and breakpoints when something is either crashing or requiring a deeper thought about how the code executes. That said, I still think there's quite a bit of improvement to be made, which is why I started building a new debugger for myself which puts a lot more focus on breakpoint-less workflow, speed of iteration and scripting ability: (demo) https://www.youtube.com/watch?v=qJYoqfTfuQk https://www.youtube.com/watch?v=qJYoqfTfuQk It's geared mainly for gamedev, but I also do use it many times to e.g debug itself.
- werat 4y agoThis looks great, very interesting approach! Augumenting the code of a running process using a scripting language is a cool idea, excited to see what comes next. I will definitely keep an eye on the project.
- Quekid5 4y agoThat's an excellent observation which I think agrees with my own. If you already have a good idea of the control flow (and thus, expected behavior), but there's some minute detail that goes wrong, you just need a few strategically placed prints to see the state evolution. If the problem is control flow related, you might first need to get a grasp of that before going into the weeds.
- AtNightWeCode 4y agoPeople who learn the tools are much more productive. Two features I often miss is that I sometimes want to copy whole data structures as JSON. There are workarounds for it in some langs. Then there is this annoying thing that some things are optimized away even in debug mode. So you have to add in variables just for debugging which is of course an anti-pattern.
- leni536 4y ago> Breakpoints, oh my breakpoints This is a good list, but one thing missing: catchpoints. Particularly useful with time travel debugging. catch throw + reverse-continue immediately tells you who threw an exception, and you can continue debugging from there.
- quelsolaar 4y agoTo me the debugger is perhaps the most important tool and I much rather have a bad editor with a good debugger than a great editor without. I find that typing code is never the limiting factor in productivity, being able to understand what your code does is, and a good debugger is a game changer. The same goes for languages, there is a lot of discussion about what various languages do, but not what debuggers are available for them. Visual studio has many faults, but IMO it runs circles around the competition when it comes to te debugger.
- whatever1 4y agoDebugging is the one reason I tolerate interpreted languages. The fact that you can pause execution and start writing commands to execute on the fly in the debug console is VERY POWERFUL.
- lispm 4y ago...and you don't need even 'interpreted languages' for that...
- quelsolaar 4y agoAs a C developer, I REALY want a interpreted C compiler with a crazy good debugger for this reason. On average I think C has really good debuggers (its a simple language that has been around for a long time) but there is so much more one could do. A few years ago i wrote a prototype called OPA, with some cool potential features. https://www.youtube.com/watch?v=pvkn9Xz-xks https://www.youtube.com/watch?v=pvkn9Xz-xks
- cxr 4y ago"Interpreted C?" (2019) <https://www.tuhs.org/pipermail/tuhs/2019-May/017790.html https://www.tuhs.org/pipermail/tuhs/2019-May/017790.html> "The ups Debugger" <https://ups.sourceforge.net/ https://ups.sourceforge.net/>
- henrydark 4y agoOne of my favorite "debuggers" is OllyDbg. I will never forget the first time I changed a few lines of assembly of a running game (starsiege tribes, around 2005), and then I saw friend-or-foe indicators through walls. That kind of "hot reloading" was special.
- cassepipe 4y agoI am personnally a big fan of gdb. There are some things you need to know before it's usable. 1. Use TUI mode with gbdtui 2. Install the packages that will give you syntax coloring in TUI mode (source-higlight something) 3. learn about Ctrl+L or alias `refresh` to `r` t redraw after your program prints if it does Bonus 4. gdb uses readline just like bash and rlwrap so its command line is configurable with the ~/.inputrc file. I personally enjoy the vi mode. Tons of other options. Bonus 5. alias gdbtui to `gdb -q -ex start --args` so it shuts up and set a temp breakpoint on you main Then you basically have a c interpreter under your hand. I remember writing a function for my class that would dump a .dot file based on the state of my tree that I could just call anytime in gdb and see my tree update in xdot. Wonderful time.
- Stratoscope 4y agoWhere I work (IBM Watson Orders) they sometimes call me "the debugger guy". I love a good debugger and what it can do for me. I don't use it only for debugging; it's also a great tool to help anyone understand a complex codebase like ours. Not sure how or why the code reaches a particular function? Set a breakpoint and then look at the call stack. It's all right there. And if you want to write some experimental code that will execute in the context of that breakpoint, just open the Python console. You can import any modules you need and test your new code immediately. I also appreciate good logging. Especially when there was a problem yesterday in one of our customer's drive-thrus. I can't attach a debugger, but I've helped make sure we have solid information in the store logs. Just the other day I was working on some testing code that would send an MQTT message to one of our services, and then it did a sleep(n) call to wait for that service to complete our task. The number of seconds to sleep was pure trial and error. Sleep too long and the tests take too much time to run. Don't sleep long enough and the tests become unreliable. So I figured I would add a bit of code to that service to send another MQTT event back to the test code after completing its task. Instead of sleeping, the test code would just wait for that signal. But where to put that MQTT call in the target service? It's a lot of rather complex code. So I slathered that service with hundreds of log.info("abcxyz") calls, every place I could find to put one. It quickly became apparent from the log where the service completed the task and it stopped logging other messages. That's where I added the "I'm done" signal. One thing that helped here is that our logging library adds the line number where each log.info() was called. So I didn't have to customize that log message, I could just copy and paste the same log.info() call hundreds of places. I think every developer should learn how to effectively use both a debugger and logging. Otherwise you're working with one hand tied behind your back. We had a conversation about this last week, including a link to an article with a title I found astonishing - "Debuggers are for Losers": https://news.ycombinator.com/item?id=35013732 https://news.ycombinator.com/item?id=35013732
- tester756 4y agoI call it debugger-driven-development and it is indeed great when you have to get quickly into huge, complex codebases. It allows you to learn them very fast. VS has great debugger for C# which allows you to do a lot of stuff when running the program, so sometimes I even develop the soft while having debugger and breakpoints attached
- brailsafe 4y agoI would be curious if there are that many frontend people that don't use a debugger. You mostly have to open devtools in the browser anyway, and it has an unquestionably sophisticated set of debugging capabilities
- pizza 4y agoThere should be debuggers for interpreted dynamic languages that can be scripted with strict type systems. Possibly like eg prolog; like if I have Python code that has a Person class defined in it, I could just check for invariant violations with the debugger, eg check self.parent != self.child and whatnot. Then if I come up with a nice check while debugging I should be able to save that as a unit test for the project straight from the debugger, etc.
- pizza 4y agoAlso edit to add: we have pretty magnificent tools for the mapping to a shared semantics of syntax- tree-sitter :: any syntax -> 1 semantics - we have tree-sitter, lsp, etc; any language can be added with an easy description. But we don't have great tools for mapping (1 semantics -> any syntax) - in some sense, the inverse of tree-sitter: inverse-tree-sitter :: 1 semantics -> any syntax If we did, we could have a universal any language meta-debugger library. The key impact of this is that anybody from some individual language could add a plugin, which could apply to every supported language that uses the subset of features that apply to that plugin. Think about the network effects of a language which has a large universe of plugins - now think about the even greater network effects if it could be a union of supported languages - that's strictly at least as good, if not vastly more network-effectful. So I think the benefit to people would increase rapidly if people contributed to it across many different languages, so it could be a good collaborative tool. I bring this up under this discussion because the debugger would be the exact best place to apply something like the inverse of tree-sitter pretend I'm not ignoring this would likely lead to a strangely organized library with lots of potential spots of inter-language interface annoyances, so it would not probably be strictly better... :)
- tooltower 4y agoThe omniscient debugging in this article was new to me. Sounds like this could be quite useful. Does anyone here have experience using this?
- magicmouse 4y agoAlthough the language i have been working on includes time travel as a built-in feature, i find that i almost never use it, because in a deductive language, it is not that easy to create a bug. Time travel is great for understanding someone else's large program, so that you can see where it goes as it is running. In large projects the instruction pointer is hop around madly throughout the code, and seeing where it goes like the path of a bird is rather handy.
- turtleyacht 4y agoIt would be nice to have event-sourcing and associated tools set up where one could drop into a REPL of some collection of docker-compose'd microservices, and step through a heterogeneous collection of the stack--from HTTP request to db query, and back out again. Certainly tools like App Dynamics and Datadog enable this app stack tracing, and Docker Compose enables composing services. To be able to play back transactions backwards and forwards among services would be a dream. Wondering if any folks have played with this kind of debugging?