Software errors are prevalent. It’s easy to make them, and it’s hard to find them. In this chapter, we’ll explore topics related to the finding and removal of bugs within our C++ programs, including learning how to use the integrated debugger that is part of our IDE.
Although debugging tools and techniques aren’t part of the C++ standard, learning to find and remove bugs in the programs you write is an extremely important part of being a successful programmer. Therefore, we’ll spend a bit of time covering such topics, so that as the programs you write become more complex, your ability to diagnose and remedy issues advances at a similar pace.
If you have experience debugging programs in another programming language, much of this will be familiar to you.
Syntax errors
Programming can be challenging, and C++ is somewhat of a quirky language. Put those two together, and there are a lot of ways to make mistakes. Errors generally fall into one of two categories: syntax errors, and semantic errors (logic errors).
A syntax error occurs when you write a statement that is not valid according to the grammar of the C++ language. This includes errors such as missing semicolons, mismatched parentheses or braces, etc… For example, the following program contains quite a few syntax errors:
Fortunately, the compiler will detect syntax errors and issue a compilation warning or error, so you easily identify and fix the problem. Then it’s just a matter of compiling again until you get rid of all the errors.
Semantic errors
A semantic error is an error in meaning. These occur when a statement is syntactically valid, but either violates other rules of the language, or does not do what the programmer intended.
Some kind of semantic errors can be caught by the compiler. Common examples include using an undeclared variable, type mismatches (when we use an object with the wrong type somewhere), etc…
For example, the following program contains several compile-time semantic errors:
Other semantic errors only manifest at runtime. Sometimes these will cause your program to crash, such as in the case of division by zero:
More often these will just produce the wrong value or behavior:
or
or
In the above example, the errors are fairly easy to spot. But in most non-trivial programs, runtime semantic errors are not easy to find by eyeballing the code. This is where debugging techniques can come in handy.