back
4 comments
I, personally, learned gradually how to use them by refusing to accept a bug fix when I didn’t understand the bug I was fixing. Gdb was first, because when I learned C it was the only freely available option. Strace likely was next when I started encountering problems that happened too long into a program’s execution to successfully use breakpoints to debug. Valgrind was likely next, when I ran into bugs where the memory corruption happened a long time before the actual crash (think use-after-free or uninitialized values).
Every time I touch gdb I curse, "why isn't this easier to inspect code, watch variables, have multiple views, etc, like Visual Studio's debugger since 1995"
There are numerous front-ends which does that.
I was curious as well, so I'm currently reading this:

https://dev.to/captainsafia/say-this-five-times-fast-strace-...

where I stumbled upon and read the ezine:

https://jvns.ca/blog/2015/04/14/strace-zine/

Speaking very personally and not axiomatically: by refusing to accept "fixes" that aren't fully understood.

If that means rejecting the PR "stop using globals in $language because that triggers a 'slab allocation' (whatever that is) which stackoverflow says is bad", and instead insisting to your boss that you spend an extra week reading kernel source/stdlib source instead of moving on from the original 2-hour-scoped bug, so be it. The outcome is far more beneficial (for you and for the product/company) in the long term.

Pratice.

strace and gdb are your friends in catching evasive bugs. Personally I would go exactly same route, though I won't modify the binary but coined an environment for it to work instead.