Funny thing. I've been in this situation, for instance, when inheriting a big, messy code base, something I don't do often anymore.
When this happens I go to the good old printf/console/whatever you have to work your way building your understanding of how the code goes, and you better be patient!
If your code is very big and/or messy AND multithreaded… well, you're in a bad spot! The best way to fight bugs in this kind of situation is by REWRITING. Isolate, create interfaces, bridges… It's basic code surgery and there's a terrific book about this "Refactoring", by M. Fowler.
If this is your own code, then you've still got to learn more about designing good code. When you really take care of learning… at first it might be daunting, I know… but hold on, it will come through the years and you will cease to fight.
You will always make mistakes but most of them will solve easily :)
We're a place where coders share, stay up-to-date and grow their careers.
We strive for transparency and don't collect excess data.