Eventually, I learned to write code that was so obviously correct and had such good error messages that I haven’t needed to use a debugger in a long time.
In fact, I don’t even know how to invoke a debugger for most languages I know.
Edit: The other good trick is to write your code so that it keeps enough state on the heap to extract useful information from core dumps. For instance, you can keep global references to lists of state that helps track issues down, and make sure they work as expected in -O3 builds. I have definitely played that game in the past.