Anyone who has been programming longer than a week knows that getting the syntax of your programming language right is the easy part of debugging. The hard part comes after that, when you need to understand why your syntactically correct program doesn't behave as you expect.
The Unix tradition encourages developers to anticipate this problem by designing for transparency — in particular, designing programs in such a way that their internal data flows are readily monitored with the naked eye and simple tools, and readily mentally modeled. This is a topic we covered in detail in Chapter 6. Design for transparency is valuable both for preventing bugs and for easing the runtime-debugging task.
Design for transparency is not, however, sufficient in itself. When you are debugging a program at runtime, it's extremely useful to be able to examine the state of your program at runtime, set breakpoints, and execute pieces of it down to the single-statement level in a controlled way. Unix has a long tradition of hosting programs to help you with this. Open-source Unixes feature a powerful one called gdb (yet another FSF project) that supports C and C++ debugging.
Perl, Python, Java, and Emacs Lisp all support standard packages or programs (included with their base distributions) that allow you to set breakpoints, control execution, and do general runtime-debugger things. Tcl, designed as a small language for small projects, has no such facility (though it does have a trace facility that can be used to watch variables at runtime).
Remember the Unix philosophy. Spend your time on design quality, not the low-level details, and automate away everything you can — including the detail work of runtime debugging.