Like all human creations, computer programs are often less than perfect. Computer code may contain various types of bugs (errors).
Errors can be syntax errors, semantic errors, or logic errors.
The most obvious type of error is the syntax error, which occurs when you write code in a manner not allowed by the rules of the language. Syntax errors are almost always caught by the compiler or interpreter, which displays an error message informing you of the problem. In Visual Studio, these error messages appear in the Output window. These messages tell you the location of a syntax error (line number and file) and a short description of the problem. Finding the cause of a syntax error is normally a straightforward process once you learn to use and understand these descriptions. For more information, see Output Window.
Semantic errors are a more subtle type of error. A semantic error occurs when the syntax of your code is correct, but the semantics or meaning are not what you intended. Because the construction obeys the language rules, semantic errors are not caught by the compiler or interpreter. Compilers and interpreters concern themselves only with the structure of the code you write, not the meaning. A semantic error can cause your program to terminate abnormally, with or without an error message. In colloquial terms, it can cause your program to crash or hang.
Not all semantic errors manifest themselves in such an obvious fashion, however. A program can continue running after some semantic errors, but the internal state of the program will not be what you intended. Variables may not contain the correct data, or the program may continue down a path that is not what you intended. The eventual result will be incorrect output. These errors are called logic errors, because while the program does not crash, the logic that it executes is in error.
The only way to detect logic errors is by testing your program, manually or automatically, and verifying that the output is what you expected. For more information, see Testing and Optimizing. Testing should be an integral part of your software development process. Unfortunately, while testing can show you that the output of your program is incorrect, it usually leaves you without a clue as to what part of your code actually caused the problem. This is where debugging comes in.
Debugging usually, but not always, involves the use of a debugger, a powerful tool that allows you to observe the run-time behavior of your program and determine the location of semantic errors. You might also use certain debugging features that are built into the language and its associated libraries. Many programmers are first exposed to debugging when they attempt to isolate a problem by adding calls to output functions, such as printf or MsgBox, to their code. This is a perfectly legitimate debugging technique, but once you have located and fixed the problem, you will have to go back through your code and remove all those extra function calls. You may also occasionally find a situation where adding new code, even a single printf or MsgBox call, changes the behavior of the code you are trying to debug.
Using a debugger, you can examine the content of variables in your program without having to insert additional calls to output the values. You can insert a breakpoint in your code to halt execution at the point you are interested in. When your program is halted (in break mode), you can examine local variables and other relevant data using facilities, such as the Watch window, the QuickWatch dialog box, and the Memory window. For more information, see Watch Window, QuickWatch Dialog Box, or Memory Window. Not only can you view the contents while in break mode, you can edit or change the contents, if you desire. In most cases, you will set your breakpoint in a Visual Studio source window, where you write and edit your code. Sometimes, you may choose to set the breakpoint in the debugger's Disassembly window instead. The Disassembly window shows you the instructions created from your source code. For more information, see the Disassembly Window. Unlike printf or MsgBox, setting a breakpoint does not add an additional functional call to your source code. Therefore, setting a breakpoint is unlikely to change the behavior of the program you are trying to debug. For more information, see Breaking Execution.
This is not all the debugger allows you to do, however. Click the See Also entries for more information.
Debugging Basics: Breakpoints | Debugging Basics: QuickWatch | Debugging Basics: Registers Window | Debugging Basics: Memory Window | Debugging Basics: Disassembly Window | Using the Debugger | Visual Studio Debugger Model