Difference between revisions of "Testing and debugging"

From Tux
Jump to: navigation, search
(Created page with "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...")
 
(Syntax debugging)
 
(5 intermediate revisions by the same user not shown)
Line 15: Line 15:
 
* Forgetting a semicolon at the end of a statement or a typo.
 
* Forgetting a semicolon at the end of a statement or a typo.
  
<source lang="c">
+
<source lang="c" line>
 
cout << "Hello!" << endl    // Error: no semicolon at the end
 
cout << "Hello!" << endl    // Error: no semicolon at the end
 
cout << "Welcome." << end;  // Error: should be endl instead of end
 
cout << "Welcome." << end;  // Error: should be endl instead of end
Line 22: Line 22:
 
* Passing a value of one type to a function that expects a value of another type.
 
* Passing a value of one type to a function that expects a value of another type.
  
<source lang="c">
+
<source lang="c" line>
 
int fcn(int x)
 
int fcn(int x)
 
{
 
{
         return (x + 5);
+
         return x + 5;
 
}
 
}
  
Line 32: Line 32:
 
         int y = fcn("Hi");    // Error: function expects an int
 
         int y = fcn("Hi");    // Error: function expects an int
  
         return(0);
+
         return 0;
 
}
 
}
 
</source>
 
</source>
Line 38: Line 38:
 
* Not including the appropriate [[header file]] when using an object or function from it.
 
* Not including the appropriate [[header file]] when using an object or function from it.
  
<source lang="c">
+
<source lang="c" line>
 
#include <iostream>
 
#include <iostream>
  
Line 45: Line 45:
 
         cout << pow(3.0, 2.0) << endl;  // Error: did not #include <cmath> and did not have using namespace std;
 
         cout << pow(3.0, 2.0) << endl;  // Error: did not #include <cmath> and did not have using namespace std;
  
         return(0);
+
         return 0;
 
}
 
}
 
</source>
 
</source>
Line 55: Line 55:
 
See below for some compiler messages and how to interpret them:
 
See below for some compiler messages and how to interpret them:
  
<source lang = "c">
+
<source lang = "c" line>
 
#include <iostream>
 
#include <iostream>
  
Line 65: Line 65:
 
         cout << "Welcome." << end;
 
         cout << "Welcome." << end;
 
}
 
}
 
+
</source>
 +
<source lang = "shell-session">
 
Compiler messages:
 
Compiler messages:
 
test.cpp: In function ‘int main()’:
 
test.cpp: In function ‘int main()’:
Line 75: Line 76:
 
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>code</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:
 
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>code</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:
  
<source lang = "c">
+
<source lang = "shell-session">
 
test.cpp: In function ‘int main()’:
 
test.cpp: In function ‘int main()’:
 
test.cpp:8:24: error: ‘end’ was not declared in this scope
 
test.cpp:8:24: error: ‘end’ was not declared in this scope
Line 89: Line 90:
 
Logic errors are typically the hardest to fix.  Common logic errors arise from:
 
Logic errors are typically the hardest to fix.  Common logic errors arise from:
  
* Loops being off by one.
+
* Loops being off by one
* Using = instead of ==, or vice versa.
+
* Using <code>=</code> instead of <code>==</code>, 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.
+
* 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 manifest itself as 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:
 
Two common ways of fixing logic errors are:

Latest revision as of 16:50, 13 January 2018

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