Testing and debugging

From Tux
Jump to: navigation, search
Computers in B361 now dual-boot Linux and Windows 10. More information can be found here

Testing and debugging are two critical components involved in writing computer programs.

Debugging refers to the process of fixing errors in a program after it has been written. The two primary types of errors are:

  • Syntax errors that prevent the program from compiling
  • Logic errors that do not prevent compiling, but cause erroneous or unexpected output

Testing refers to the process by which a program is determined to be functioning properly and free from logic errors.

Debugging

Syntax errors

Syntax errors are typically the easiest to fix. Common instances of syntax errors would be:

  • Forgetting a semicolon at the end of a statement or a typo.
1 cout << "Hello!" << endl     // Error: no semicolon at the end
2 cout << "Welcome." << end;   // Error: should be endl instead of end
  • Passing a value of one type to a function that expects a value of another type.
 1 int fcn(int x)
 2 {
 3         return x + 5;
 4 }
 5 
 6 int main()
 7 {
 8         int y = fcn("Hi");    // Error: function expects an int
 9 
10         return 0;
11 }
  • Not including the appropriate header file when using an object or function from it.
1 #include <iostream>
2 
3 int main()
4 {
5         cout << pow(3.0, 2.0) << endl;  // Error: did not #include <cmath> and did not have using namespace std;
6 
7         return 0;
8 }

Syntax debugging

When a program will not compile because of syntax errors, the compiler typically does a good job of telling you exactly what line and column the error occurred in as well as the specific type of error. Note that if there are multiple syntax errors, the compiler may only catch some of them. As errors are fixed and the user attempts to compile again, the additional errors will be caught by the compiler and these must also be fixed.

See below for some compiler messages and how to interpret them:

1 #include <iostream>
2 
3 using namespace std;
4 
5 int main()
6 {
7         cout << "Hello!" << endl
8         cout << "Welcome." << end;
9 }
Compiler messages:
test.cpp: In function ‘int main()’:
test.cpp:8:2: error: expected ‘;’ before ‘cout’
  cout << "Welcome." << end;
  ^

Note that even though there are two errors, only the first is caught. To fix this error the semicolon needs to be placed before the code in line 8. Really where it should go is at the end of line 7. Upon fixing this error and compiling again, the following error occurs:

test.cpp: In function ‘int main()’:
test.cpp:8:24: error: ‘end’ was not declared in this scope
  cout << "Welcome." << end;
                        ^

Again, the compiler notices there is no such thing as end and points it out. Either there should be an identifier (i.e. a variable) called end or the programmer mistyped and meant endl. Upon fixing this error the program will compile.

Getting experience with syntax error messages from the compiler and fixing them is essential for a programmer.

Logic errors

Logic errors are typically the hardest to fix. Common logic errors arise from:

  • Loops being off by one
  • Using = instead of ==, or vice versa
  • Attempting to modify an element of an array or dereferenced pointer that is out of bounds -- this type of error usually results in a segmentation fault
  • Deep/infinite recursion, leading to a stack overflow which may or may not manifest itself as a segmentation fault

Two common ways of fixing logic errors are:

  • Adding output (e.g. cout) statements throughout the code to display where the code is currently executing and/or what the values of variables are
  • Using a debugger such as gdb

Testing