GDB and some fprintf calls cut it most of the time. The worst kind of bug is when the program segfaults into oblivion and works fine under GDB but in 99% of the cases that's related to uninitialized memory, which might be a bit hard to find but is quite simple to fix (it's the worst because it sometimes takes a while to figure out where you forgot to initialize variables when it's unrelated to a new change and happened to just not occur during previous changes).