I don't usually use a debugger, maybe once every couple weeks but it's not the first thing I go to.
The most important tool in my job is so ubiquitous that I almost forgot to mention it--stack traces. Over 90% of the problems I encounter can be solved by examining a stack trace. This tool isn't always very helpful depending on your language, but when they are implemented well by a language they can save you an amazing amount of time.
I guess the second most common way I detect simple problems is that it's probably the code I just changed. I run unit tests quite often so I generally know what I just broke.
For more complex development and debugging I might add some debug or trace level log statements. I consider development problems a good guide to help me place production trace/debug logging information, which leads me to:
You don't always have a debugger handy. In production it might be impossible to run a debugger (Heck, it might be impossible to access production machines except for logs depending on how secure your company is). There are also languages where hooking up a debugger just takes too long or maybe there just aren't good debuggers available.
If you have been coding all along using logic and debug/trace level logging it can simply be the case of examining your excellent log statements (Possibly increasing the log level) to figure out the problem without even accessing the hardware.
Although I think debuggers are a powerful tool, don't let them be the only tool in your toolbox!
printfbecause when it is time to go to production, it can be turned off in a single location (e.g., set log level = warn) instead of having to worry about commenting out a bunch of printf lines scattered throughout the code. – BryanH Jan 17 '13 at 00:46int 0x10, orCC 10– Cole Tobin Jan 18 '13 at 22:17