If debugging takes bugs out of a program, programming must put bugs into a program. There are many different kinds of bugs that programmers can and do put into their programs:
Only the first four kinds of bugs are considered this semester. Syntax and link errors are detected at compile-time by one part of the compiler system. Specifically, the compiler component, the middle part of the compiler system, provides diagnostic messages that help programmers locate and identify syntax errors. The linker (or loader on some platforms), the last part of the compiler system, detects link errors. The compiler system cannot detect logical and runtime errors, and they are typically much more difficult to locate. Most modern IDEs, including Visual Studio, have a built-in debugger, which is useful for locating these errors.
Syntax Errors
A correct program consists of a sequence of keywords, symbols, and identifiers (an identifier is a name that a programmer gives to a programming element such as a variable, function, class, etc.). The sequence must be flexible enough to allow programmers to write the various programs needed to solve new problems while being sufficiently well-defined pattern that the compiler can translate programs into the machine code that a computer can run. Each programming language specifies the specific pattern that its compiler recognizes and accepts. The pattern forms the language's syntax. Any deviation from this pattern represents a syntax error.
Every compiler, specifically the compiler component, will detect syntax errors when compiling the program. However, the error messages or diagnostics will vary greatly between different compilers. Sometimes, the error messages are very accurate, while at other times, they provide little more than a starting point for your debugging session. Additionally, some systems, such as Visual Studio, provide a dynamic syntax checker that runs in the background while you write code. Studio's syntax checker, IntelliSense, underlines potential syntax errors with a red wavy line. After correcting a syntax error, it may be necessary to "click" the mouse pointer to the end of the corrected statement to allow IntelliSense to "catch up" and remove the underlining - it is even sometimes necessary to save the file to trigger the update.
(a)
(b)
(c)
(d)
Visual Studio error detection and reporting. An illustration of IntelliSense and the error output from Visual Studio.
Intentionally creating a syntax error by removing a semicolon from the "Hello, World!" program.
IntelliSense underlines the "return" statement - this is NOT the syntax error but is the point where IntelliSense detects the error.
The output window (usually at the bottom of Visual Studio) after attempting to build the Hello World program with a missing semicolon. The error is reported on line 7 but is actually at the end of line 6. Errors may occur above the reported line but are never below.
Double clicking on an error in the output window (c) will cause Studio to display the file containing the error, will move the cursor to the line where the error is detected, and will mark the reported line with a pointer (circled in red).
When Studio attempts to build a project (5:43) that contains syntax errors, it reports those errors in the "Output" window (Figure 1(c)), which is generally at the bottom of the Studio IDE. To most effectively use the information contained in the output window, follow these five "rules of thumb:"
Five Rules of Thumb: Using The Output Window Error Information
One syntax error can be detected more than once, and it can cause multiple problems in the program. So, it is always best to start at the top of the output window (i.e., with the first error) and to work down one error at a time. Depending on the error, with experience, you can work with more than one error at a time, but for now, it's best to fix the problems one at a time.
The fastest way to locate an error in the text editor is by the error message in the "Output" window at the bottom of Visual Studio (you may need to select the "Output" tab). Scroll to the error message describing the error you wish to correct next (the line highlighted in blue in Figure 1(c)) and double-click the message. The debugger moves the file containing the error to the front in the editor and marks the line where it detected the error with a pointer along the left edge (Figure 1(d)). This fast navigation "trick" is of little use with tiny programs like Hello World but becomes very helpful as programs increase in size and spread over multiple files.
The compiler reports where it first locates the error, which may not be the error's actual location. So, begin on the line where the debugger reports the error. If the error is not on that line, then work backward (i.e., upward) one line at a time until you find the error. Note that the error will never be below the reported line.
The keywords, symbols, and identifier patterns form a language's syntax, acting like guideposts during the compilation process. While the compiler finds the correct syntax elements where it expects them, the compiler "knows where it is," but it can "get lost" when there is a syntax error. When the compiler is lost, it cannot syntax check the code that it reads. Eventually, the compiler will "see" a major signpost (like the beginning of a function) and "figures out where it is." Once it "knows where it is," it resumes syntax checking the program but discontinues generating machine code. The computer scientists that create compilers call this technique error recovery. The compiler doesn't recover in the sense that it corrects the error, but it does recover enough that it can continue checking some of the program. If you correct a syntax error, recompile the program, and see MORE errors than you did before the correction, DON'T put the error back - the compiler is just checking code that it previously skipped before it could recover.
Save yourself some time: I have helped students who have reported Googling the error number (e.g., C2143 or LNK2019) that appears as a part of the error message in the output window. You will rarely find more information doing this than what the compiler reports in the output window. You will make better use of your time and effort learning how to read C++ and how to spot the details that are wrong or out of place.
In the example above, the error message clearly identifies the problem: Missing ';' before 'return'. However, some compiler systems occasionally produce unhelpful diagnostics, some that are misleading, and some that are utterly incomprehensible! In the early 1980s, I witnessed an error message from a C compiler that "helpfully" reported an error, "Bad Tuna." Fortunately, compilers continuously improve their error messages.
Link (LNK) Errors
Link errors arise from the linker, the last component or program of the compiler system to run. Although many problems cause link errors, only one occurs frequently in the small programs appearing in the first few textbook chapters. It represents a user error that is very easy to make but is also easy to correct. To demonstrate this problem, begin with the following simple and correct program:
#include <iostream>
using namespace std;
int main()
{
int number;
cout << "Please enter a number: ";
cin >> number;
return 0;
}
Build the program
Run the program (without debugging)
With the console window still open (i.e., don't enter a value at the prompt and don't press the enter key), make a non-significant change (e.g., add an empty line at the bottom of the program)
Save and rebuild the program
Run the program again
(a)
(b)
1>------ Rebuild All started: Project: Error3, Configuration: Debug Win32 ------
1>C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V110\Microsoft.CppClean.targets(75,5):
warning : Access to the path 'E:\TMP\CS1410 PAST\ERROR3\DEBUG\ERROR3.EXE' is denied.
1>C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V110\Microsoft.CppClean.targets(75,5):
warning : Access to the path 'E:\tmp\cs1410 past\Error3\Debug\Error3.exe' is denied.
1> Error3.cpp
1>LINK : fatal error LNK1104: cannot open file '****************.exe'
========== Rebuild All: 0 succeeded, 1 failed, 0 skipped ==========
(c)
A link error caused by a "busy" file.
Code used to demonstrate a common link error.
Steps to create the link error.
The illustrated error message in the output window (c) wraps the second and third lines to improve the presentation. The highlighted line is the key to solving the problem: it identifies it as a LINK error (additionally, the error number begins with LNK). The compiler component detects and reports syntax errors as it processes the source code file, allowing it to include line numbers with the error messages. However, the linker processes object code files, which do not correlate source code lines with the machine code. So, programmers can't double-click the error in the output window and jump to the corresponding error location in the editor. The last part of the error message states, "cannot open file *.exe" (the asterisk replaces the file name as it will vary).
When the compiler system successfully compiles a program, the linker will create a new executable file whose name ends with a .exe extension. In this example, when the linker tries to create the new executable file, it can't remove the old file because the program is "busy" (i.e., it is still running and in use). Simply closing the previous console window before rebuilding the program resolves the error. This error usually occurs when you iconify the console window while continuing to work on the code and then forget to close the window before recompiling the program.