I trend more towards print debugging than breakpoints.
To me the beauty of print debugging is you can see the flow, and see it quickly in contrast to the debugger. Simply with the debugger, a lot of the time is spent stepping past (at the moment) superfluous breakpoints.
Step, step, step, step, …, step, step, BANG!
Versus a quick BANG preceded by a trail of debris I can then postmortem. I use both, naturally, but prefer the crashes with a debris field than walking on eggs to potential disaster.
Which is why a good reversible debugger is so powerful. (I use rr-project.org and Pernosco but I imagine undo.io is similar.) Don't worry about stopping at the right point. Go back to the critical points over and over again, and go backwards to what generated an input. If you like logs, the debugger has facilities for generating tailored ones. Or manually generate your own debugging session log trail, generating entries throughout the execution in any order, and see them in execution order.
To me the beauty of print debugging is you can see the flow, and see it quickly in contrast to the debugger. Simply with the debugger, a lot of the time is spent stepping past (at the moment) superfluous breakpoints.
Step, step, step, step, …, step, step, BANG!
Versus a quick BANG preceded by a trail of debris I can then postmortem. I use both, naturally, but prefer the crashes with a debris field than walking on eggs to potential disaster.