Posted by never_inline 7 days ago
printf debugging works in all of them, even the build system and shell scripts.
A debugger can be great, no question about it, even for remote debugging. In my experience, I’ve seen fewer people effectively debug unfamiliar systems quickly.
Not printf exactly, but I've found bugs with a combination of mprotect, userfaultfd and backtrace_symbols when I couldn't use HW breakpoints.
Basically, mark a set of pages as non-writable so that any writes trigger a pagefault, then register yourself as a pagefault handler for those and see who is doing the write, apply the write and move on. You can do this with LD_PRELOAD without even recompiling the debugee.
Note: I do work at MSFT, I have used these capabilities but I’m not on the debugger team.
https://learn.microsoft.com/en-us/windows-hardware/drivers/d...
i haven’t seen this type of capability used in too many companies tbh and it seems like a lot of opportunity to improve stability and debugging speed and even code exploration/learning (did i break something ?)
Stumble upon some corrupted memory? Just put a watch point on it, and run the program backwards. Two weeks just turned into two minutes.
https://rr-project.org/ already has enough example usage to get you going on the home page right there.
WinDbg has time travel debugging, and is arguably 'more excellent': https://learn.microsoft.com/en-gb/windows-hardware/drivers/d...
A concrete use case for this is catching memory corruption. If your program corrupts a known piece of memory, just set a hardware watchpoint on that memory address and BOOM, the debugger breaks execution on exactly the line that's responsible for the corruption. It's a fucking godsend sometimes.
Vscode (or an editor with ADP support) supports unconditional breakpoints, watchpoints, and logpoints (observe & log values to the debug console).
In particular, REPL tools will work on remote session, on pre-production servers etc. _if_ the code base is organized in a somewhat modular way, it can be more pleasant than a debugger at times.
Makes me wonder if the state of debugging improved in PHP land. It was mostly unusable for batch process debugging, or when the server memory wasn't infinite, which is kinda the case most of the time for us mere mortals.
I use IPython / JShell REPLs often when the code is not finished and I have to call a random function without entrypoint.
In fact its possible to jump to the graphical debugger from the Python REPL when running locally. PyCharm has this feature natively. In VSCode you can use a simple workaround like this: https://mahesh-hegde.github.io/posts/vscode-ipython-debuggin...
VS, on the other hand, gets worse with every release. It is intolerably slow and buggy at this point. It used to be a fantastic piece of software, and is now a fantastic pile of shit.
> ... py-list, py-up and py-down, py-bt, py-print, and py-locals GDB commands
> [ DDD, pyclewn (vim), trepan3k, Voltron, gdbghidra ]
gdbghidra: https://github.com/Comsecuris/gdbghidra
radare2: https://github.com/radareorg/radare2
voltron: https://github.com/snare/voltron
And from https://news.ycombinator.com/item?id=41943521 :
> pyvmidbg (libVMI + GDB)
But that's archived.
There's a QEMU gdbstub GDB interface.
To print registers with GDB:
info reg
info all-registers
i r a
gdb -p `xprop _NET_WM_PID | sed 's/.*= //'`
I think under Wayland it might not be possible since Wayland gratuitously breaks all nice things.Kind of a hybrid of logging and standard debugging. "everything" is logged and you can go spelunk.
For example:
The ”debug” package on npm is something in between, as it requires inserting debug statements but they are hidden from output unless an envvar like DEBUG=scope.subscope.*,otherscope is used.
pdb is great for python, though.
I simply use conditional break points to break when whatever go routine happens to be working on the struct I care about.
Is there more to the issue?
- Things like "continue", "step" are no longer a faithful reproduction of what the program does in real time, so it's more difficult to understand the program's behavior. Some timing-related bugs simplify disappear under a debugger.
- There's usually some background thread that's logging things to console, which reduces to problem 2 in my comment.
I haven't used Go that much. I imagine since goroutines are such a cornerstone of the language, the go debugger must have some nifty features to support multi-(green)-threaded debugging?
if (condition)
print("");
Then add a breakpoint on the print. Calling print ensures the line with the breakpoint won't be optimised out (rarely matters as I'm normally debugging in... debug mode, but it's just a reflex at this point, and I need to put something in there)And I work in C#, so I have no clue why there's no option to inject the condition and a call to Debugger.Break() and then have the JIT recompile the function live. It would actually make conditional breakpoints usable!
It seems to me that this is one of the many phenomena where people want to judge and belittle their peers over something completely trivial.
Personally, I get the appeal of printing out debugging information, especially if some bug is rare and happens in unpredictable times (such as when you are sleeping). But the amount of info you get this way is necessarily lower than what can be gleaned from a debugger.
As far as I'm concerned, breakpoints and backtraces, especially of crashes, are the superpower of debuggers. Where they are not immediately applicable, I usually don't bother.
Print debugging optimizes for timing detail and fidelity.
Debuggers optimize for data detail, at the expense of timing detail and fidelity.
In my opinion - timing & order of events is actually more meaningful.
I often don't need the extra data detail, and the debugger is going to change timing in meaningful ways.
Both are skills - both have their place. Know when logs are useful, know when debuggers are useful. Don't get stuck in the fallacy of "The one true way!" - that's the only thing I can promise is bullshit.
If you've never debugged a problem that goes away when a debugger is attached - you're woefully unprepared to have this conversation (It's much rarer, but I can even talk about times where adding a single print line was enough to change timing and make the issue harder to reproduce).
At the very least - with prints you get a tangible record of the order of operations during a reproduction. It doesn't go away, I don't have to remember how many times I've hit continue, I don't have to worry about whether pausing at this breakpoint is changing the world (and it is, because other things keep chugging - the network doesn't give a fuck that you're paused at a break point).
No one can argue how many keystrokes and brain cycles it saves using a debugger vs going through the task printing every variable.
Spread the good word!
Is this not taught anymore? I started on borland C (the blue one, dos interface) and debugging was in the curriculum, 25+ years ago. Then moving to visual studio felt natural with the same concepts, even the same shortcuts mostly.
- run my tests, running any previous failures first - drop into the debugger when a test fails (or of course, hits a breakpoint) - end the test run after the first failure
use debugger to figure out what went wrong, fix it, wash, rinse, repeat
Setting up a debugger is the very first thing i do when i start working with a new language, and always use it to explore the code on new projects.
Being able to ask questions about the parts that are unclear (or just plain wrong) is so much easier than trying to cram the entire thing into my brain RAM.
In my experience it actually helps me learn faster too, since I rarely get stumped on random gotcha's anymore.
Not a second of that was a waste because xdebug (like all debuggers) is just that amazing.