How do I debug my program?
This is a critical skill in programming, and you must learn how to do it well. It is largely an art; there is no single way to do it, and the best way to learn it is to do lots of it. Here are some ideas to get you started, based on our experience.
The Zen of Debugging
The biggest obstacle to overcome is your belief that your code is right and the computer is somehow wrong. Compiler and library bugs exist, but they are very rare compared to programming errors. So, 99.99999% of the time the computer is doing exactly what you told it to do, and you just told it wrong. Your task is to find the wrong thing you said - it is in there somewhere!
The overall best way to find a bug is to gather information about the conditions under which the bug happens and exactly what the bug does. There are a variety of ways to do this, such as trying different input to see if there is a pattern in the bug's behavior, or checking program flow and variable values.
As you come to understand the bug, you can begin to deduce what parts of your program are relevant, and start to zero-in on ever smaller parts of your program. Eventually you can ask "What does this line of code do compared to what it is supposed to do?" and you will find the exact wrong thing in your code.
Most of these are "stupid" small errors or typos that passed the compiler, but expect many of them to be "profound" errors, especially if you are learning the programming language and the software concepts.
The overall best way to gather information is to use the debugger. That's why professionals use them. The debugger is your friend! Learn how to use it, and how to use it well! It will repay your learning time investment with truly extraordinary interest.
Consult the course materials and your IDE documentation and us, for help with learning and using the debugger.
What We Expect
Avoiding learning and using the debugger is shortsighted, unprofessional, and, frankly, stupid. We expect you to be using a debugger on all your projects. When you ask us for help finding a bug, we expect that you have already used the debugger yourself and have gone as far as you can.
How to Debug:
Use the debugger to step through your program. Check program flow and the values of variables. See if the program goes where it should, and that input values, function arguments, and the results of calculations are what they should be. As soon as you see something that is wrong, stop and try to figure out what caused it. As needed, restart the program and go through that section again and in more detail. To save time, use breakpoints and the step-over buttons to skip through parts of the program that you know to be good.
Once you find a bug and understand it, go ahead and fix it right away, and recompile and rerun the program. If you have more than one bug, they tend to interact in really nasty and confusing ways. Don't waste time trying to figure out all the perverted things a screwed-up program is doing. It is almost always better to remove each bug immediately rather than try to understand what is happening with multiple bugs.
However, if your program has a zillion bugs, and really is a screwed-up mess, the problem may be more serious. Often your approach to the problem, your program design, or your understanding of how to write the code is fundamentally flawed. Take a break and review what you are trying to do - is there a bug in your ideas or your knowledge?
Once you understand what to do, sometimes it is easier to throw part or all of your code away and start over, than straightening out a mess you made before you understood the problem or how to write the code. Happens to us all the time! "Plan on throwing the first version away!" is a slogan in software development.
Always run your program in debugging mode from the beginning, and keep it there until you are pretty confident in your program. Your new program almost certainly has some bugs, so why not start with the debugger already available? The debugger can prevent certain system crashes caused by some bugs, saving you time as well.
How does the debugger work?
The debuggers we want you to use are "symbolic debuggers", and are very sophisticated programs in their own right. Normally, the compiler and linker throw away all information about function and variable names (the "symbols"), leaving just the raw machine instructions. When you put your project into debugging mode, the compiler and linker arrange to save the names and memory locations of all variables and functions in special data files for use by the debugger, and insert special "break" code into the compiled program to mark where in the machine code each statement starts and where each function call is made.
When you run your program under the debugger, the CPU encounters the "break" code inserted at the beginning of the machine code for an original program statement or function call. The break code calls the debugger, which then does whatever you've specified with your debugging options or functions, such as pausing before executing the statement.
Using the information saved during compiling and linking, the debugger can open the appropriate source code file, display it in a window, and show you which statement produced the machine code that is about to be executed. Using other saved information, it can also show you the contents of the memory locations corresponding to the variables currently on the run-time stack.
There are some important implications of how the debugger works: First, although the basic features are pretty reliable and easy to use, it is a very complicated program with lots of extra features. So realistically, you should expect some bugs and quirks in the debugger itself. Second, the debugger actually modifies the size and locations of things in memory compared to a normally-running program. In some cases, the exact symptoms of a bug can change when you use the debugger, especially when you have problems with bad pointers and arrays, whose symptoms are hypersensitive to exactly where things are in memory. So, if using the debugger changes the bug symptoms, suspect your array and/or pointer code!
Why is it called a "bug"?
The story starts in the 1940s, in a U.S. Navy computer project using one of the first general-purpose computers, the Mark I, which was an electromechanical computer predating even the ENIAC. The programmer found that a problem was due to a dead moth stuck in a relay in the machine. Removing the bug allowed the computer to run as programmed. The programmer, U.S. Navy LTJG Grace Hopper (later Admiral), a famous computing pioneer, preserved the actual bug in her project notebook where it can be seen to this day. Adm. Hopper developed one of the first compilers, led the development of business applications of computers, and co-invented COBOL, still the single most heavily-used computer language.
The Navy's Grace Hopper site.
More about Grace Hopper and other women in computing.