PerlWiz - Debugging

Click here for the perlwiz.biz documentation home page
Contents Prior Page Next Page

This exercise gives a sample program that has various mistakes in it. Some are syntax errors - i.e. the structure of the language is incorrect. Some are logical errors - the meaning of the programming commands was not as intended.

We will look at some techniques we can use to test what is happening while the program is executing to help us discover the source of the problems.

Creating the test program

The test program is designed to store three values, and find the total and average of those three values. The percentage of this total that the first item takes is then calculated and the values displayed on the screen.

Then the total is multiplied by 1, 2, 3, 4 and then 5 (i.e. loops around five times) in order to see how much the cost would be in "bulk".

#!/usr/bin/perl

$item1 = 10.00;
$item2 = 20.00
$item3 = 30.00;
$total = $item1 * $item2 * $item3;
$average = ($item1 / $item2 / $item3) / 3;
$item1_perc = ($total / $item1) * 100.0;

print "Item 1 is $item1\n";
print "Item 2 is item2\n";
print "Item 3 is $item3\n";
print "Total is $total\n;
print "Average is $average\n";
print "Item 1 is $item1_perc% of the total\n\n";

for ($i=0; $i<5; $i--(
{
  print "$i x $total = " . ($i * $total) . "\n";
}

Create a new file by clicking on the button on the toolbar, and typing (or copying and pasting) the program above.

When saving the file, use the button on the toolbar (or Ctrl+Alt+A) rather than Ctrl+S so that you can keep the file saved as a temporary file (as this is for test purposes only).

Execute the program by clicking on the or button to execute to the text page.

You should find that nothing is returned. What has happened? Try using the syntax check - - button to see if the program is properly formed.

Various syntax errors are displayed in the green box at the bottom of the window. Here's the problems and solutions:-

Scalar found where operator expected at line 5, near "$item3"

Double-click on this line, and the cursor jumps to line 5 in the program listing. This looks fine.

But check on the next line down in the error listing, and you have a suggest - (Missing semicolon on previous line?)

We look at line 4, and yes, a semi-colon is missing from the end of the line. So line 4, after correction, should read:-

$item2 = 20.00;

Bareword found where operator expected at line 14, near "print "Average"

Wow! Again, if you look at the line below this by scrolling down a bit, we can see a further explanatory message that says (Might be a runaway multi-line "" string starting on line 13).

So double-click on this message to take us to line 13. If we look carefully, the closing quotes are missing from the print statement, so the compiler has second-guessed us correctly again! Well done compiler!

After correction, line 13 should look something like this:-

print "Total is $total\n";

We can ignore the following suggestion (Do you need to predeclare print?) as we've found the problem already.

A lot of the following errors are to do with the missing quote, so let's run the syntax check again before carrying on looking at the error messages.

This clears most of them up, leaving us with:-

syntax error at line 17, near "--("

Let's double-click on this error message to take us to line 17.

We can see that the closing bracket on the for loop is the wrong way around. We can change it around so that line 17 now becomes:-

for ($i=0; $i<5; $i--(

Unrecognised character ...

If you ever get an "unrecognized character..." error message, it may be that the program listing has been copied in incorrectly. Just remove the leading spaces on the program line where the error occurs, and put them back in again with the space bar and syntax check again. The problem should disappear. 

Executing the program

If you syntax check again, you should see syntax OK appear in the message box. That means the Perl instructions are all syntactically correct (i.e. use the right language, but not necessarily in the right order).

Let's execute the program to see what we get  

Execute the program by clicking on the or button to execute to the text page.

Aaaarghh!!  The program seems to be counting downward in the negative range of numbers. Something is clearly not right.

To stop the program running until eternity or the next power cut, click on the button on the toolbar. Time for some investigation.

Scroll back up to the top of the Text Output window, and you should see a number of inconsistencies:-

We could probably guess the reasons for this by looking at the source code. However, we can actually see what is happening on a line-by-line basis as we go through the program.

Executing to a breakpoint

We are interested in tracking what happens after the first three variables have been given values. To do this quickly, we can set a breakpoint on line 6 as shown in this diagram - by clicking on the bullet to the left of line six to put a tick against it.

If we now click the button to execute in debug mode, the program will start executing, but pause just before executing line 6. If you look on line 6 of your listing, you will see that it has been highlighted in vivid red. This shows where the next line will be executed.

Inspecting the contents of variables

If you try hovering the mouse arrow over the word $item1 anywhere in the program - on line 6 will be fine - then a small tooltip will show the contents of the variable at this point in time. This should show as 10 - notice that the trailing .00 has been removed as it is not really relevant. Try the same with $item2 (should show 20) and $item3 (should show 30).

Try it with the $total variable. No tooltip shows. This is because the $total variable has not yet been set.  We would expect it to be 60 when it is set (the total of 10, 20 and 30).

Note that if you have trouble seeing the tooltip, try clicking into the editor first.

Stepping - Executing a single line

To execute only the highlighted line (and to move the highlighter onto the next executable line), click on the button on the toolbar. If you now hover the cursor over the $total variable, it should show a value of 6000 instead of 60. Why is this? If we look at the line that has just been executed, we can see that the * symbols mean "multiply" when we actually wanted "addition" - i.e. the + symbol. So we will need to change the * to a +.

It is not recommended that you change the listing whilst it is executing, as inserting or removing lines can cause the highlighter to highlight the wrong line, and throw breakpoints off visually.

However, in this case, changing the * to + will not add or remove any lines, and the line will not be executed again, so there is no possible confusion, so we can change it without any ill effects to further execution. The line should now read:-

$total = $item1 + $item2 + $item3;

Of course, the value of $total will still be wrong.

We will start execution again to avoid any further confusion by clicking on the  button on the toolbar to halt execution and the button to execute in debug mode again. The same line will be highlighted again when the breakpoint is reached, and clicking on the button will cause this to be executed. Hovering the cursor over the $total field again should now show a value of 60 as we would require.

Click on the button again to execute (or "step over") the next line:-

$average = ($item1 / $item2 / $item3) / 3;

Hover the cursor over the $average variable. You should get a value of 0.0055555 etc. - not what we were expecting. If we look at the line, we can see that we are using the / operator which divides the three variables. We need to sum them, and divide them by three.

In fact, as we have already summed the items, we may as well use the contents of the $total variable and divide that by three. Let's change the line as follows:-

$average = $total / 3;

We may as well carry on, as this should work out to work next time we execute the program.

Click on the button again to execute (or "step over") the next line:-

$item1_perc = ($total / $item1) * 100.0;

Hover the cursor over the $item1_perc variable. You should get a result of 600. This is too big. If we look at the formula, we can see that we have $item1 and $total the wrong way round (total must be bigger than $item1, so we are going to get a value much greater than 100% - when we want item 1 as a proportion of the total. We can change the line to read as follows:-

$item1_perc = ($item1 / $total) * 100.0;

Let's step over the first print statement using the  button. Switch over to the Text Ouput tab, and you can see the first line of output has appeared (you may need to move the scroll bar to the left slightly):-

Item 1 is 10

Which is correct. Step over the next print statement using the  button. We should see the next line appear. This time, it says:-

Item 1 is item2

The name of the variable instead of its comments have been displayed. Click back on the Source tab. We can see line 11, just above the next line to be executed (highlighted in red) is missing the $ before the variable name to be displayed, which is why we are not seeing the contents of the variable. Amend this line to read as follows:-

print "Item 2 is $item2\n";

Let's step over the next print statement using the  button. Switch over to the Text Ouput tab again. The third line is displayed correctly as:-

Item 3 is 30

The name of the variable instead of its comments have been displayed. Click back on the Source

Click on the button again. The total correctly displays as follows:-

Total is 60

The average is going to display incorrectly, so let's re-run the program, but add a new breakpoint.

Click on the  button to terminate the program, and click on the bullet to the left of line 17 to put a breakpoint line here.

Execute the program again by clicking on the button to execute in debug mode.

Oops!  Forgot to take the breakpoint off line 6. Execution has paused here first.  No worries - just click on the button again to continue processing until then next breakpoint on line 17.

Now click on the Text Output tab.  The values are now what we expect them to be.

Debugging a loop

Our breakpoint on line 17 has triggered after the loop has executed once. We can see that the count (which is supposed to be from 1 to 5) is starting at 0.  If we continue by clicking on the button again, then because the breakpoint is within the loop, it will be triggered again the next time around the loop. We can see that the next number in the sequence is -1.  So each time around the loop, we seem to be decreasing the counter by 1 instead of increasing it.

Switch back to the Source tab. If you hover you cursor over the $i variable, you can see it is -1 - as we would expect to see. The line that controls where we are counting from / to (line 17) is as follows:-

for ($i=0; $i<5; $i--)

We can see that the starting value is wrong - it should be $i=1 and the counter is counting down the $-- - this should be $++. Thus the line should really read:-

for ($i=1; $i<5; $i++)

If we terminate the program and take off all breakpoints, and execute again, then the output should look better. Except, the count is from 1 to 4. Why would this be? If we look at the terminating condition, it will carry on while the counter is LESS THAN 5 - i.e. when it reaches 5, it will terminate. Perhaps we should change this to LESS THAN OR EQUAL TO 5, or less than 6:-

for ($i=1; $i<=5; $i++)

Try executing the program again. All working now! Debugger is debugged.

 

(c) Copyright 2003-4 Arctan Computer Ventures Ltd.   All Rights Reserved.
If you have any issues regarding this on-line help, please contact the author by clicking here.
Alternatively, you can leave a voice message on +44(0)7050-618-297 or fax on +44(0)7050-618-298

This Page was last updated: 20 March 2004 09:48