There seem to be two traditions in the field of debugging. One is to use things like printf or kprintf, to print the current state of a program.
The other is to use some of the many debuggers that are around, and inspect the state of the running program, along the call stack.
I think this is, to some degree, probably often a kind of personality-related preference. Personally, I like to use printf, because it matches well with what I call "the scientific method of debugging":
1. I have an idea what a program should do
2. I observe something that is different - that is, my mental model of what the program does diverges at some point from reality
3. I try to make a more refined mental model of what might be happening
4. I test that mental model by inserting print commands at very specific points in the code
5. I observe what happens. based on that, I possibly modify the code, and go back to number 2.
For me, this has turned out to work surprisingly well in a number of domain, such as concurrent real-time systems, complex signal processing, and more. (The nice thing abpout printf in concurrent systems is that it serializes events, which helps).
Other people, I see, prefer to use a debugger. My hypothesis is now that this is due to a combination of both personality as well as concrete tasks where a debugger might be suited better.
So, what I am interested in is your observations of specific cases and circumstances when one methodology might work better than the other. Or maybe it also matters how to do each, to have good results.
What is your experience?
However, for some things like debugging Windows kernel trickery it is impossible to use print statements.
Personally I like debuggers.