A Sample Program

To demonstrate how the Debugger can be used, take the example of an internal office program called BIRTHDAY. The BIRTHDAY program asks users for their birthdays and then tells them how many days they have until their next birthday. The program works fine for the programmer:

>RUN BP BIRTHDAY

The screen is cleared and the following prompt appears (with the underline representing the position of the cursor.) :

ENTER YOUR BIRTHDAY: MM/DD/YY

 A date is entered:

ENTER YOUR BIRTHDAY: 6/4/65

The program converts the date and then prints out how many days there are until the programmer’s next birthday.

ENTER YOUR BIRTHDAY: 04 JUN 1965

ON 06/04/1990, IN 319 DAYS, YOU WILL BE 25 YEARS OLD.

 

>

The programmer was satisfied by this performance, since the tricky part of the program was to make sure that it did not report a birthday that had already passed (e.g., IN -46 DAYS, YOU WILL BE 24).

Since the test above was performed in July and the date entered was in June, the tricky part seemed to have been solved.

Later the same day, however, it was reported that the program did not work. In particular, when supplied a date in September, the program still jumped ahead a year:

ENTER YOUR BIRTHDAY: 3 SEP 1961

ON 09/03/1990, IN 410 DAYS, YOU WILL BE 29 YEARS OLD.

The programmer quickly examined the source code but could not find an error. However, using the Debugger, perhaps the user can discover something the programmer could not.

Printing Source Code

First, run the program with the D option, which forces the program to enter the Debugger before executing line 1.

>RUN BP BIRTHDAY (D)

Before the program begins execution, the Debugger is invoked and E1 is printed, signifying that it stopped before executing line 1. The asterisk (*) is the Debugger prompt.

*E1

*

The first thing is to examine the source code. Before you can access the source code, you need to turn trace on with the T command.

*T<ENTER>

The source code is now available for listing by the Debugger with the L command. Since it is a short program, L can be used with the * option, specifying that the entire source code item should be printed.

*L*

001   PROMPT " "

002   DIM BIRTHDAY(3), TODAY(3)

003   EQUATE TRUE TO 1,

004      FALSE TO 0,

005      BIRTH.MONTH TO BIRTHDAY(1),

006      BIRTH.DATE TO BIRTHDAY(2),

007      BIRTH.YEAR TO BIRTHDAY(3),

008      THIS.MONTH TO TODAY(1),

009      THIS.DATE TO TODAY(2),

010      THIS.YEAR TO TODAY(3)

011

012   INCREMENT = FALSE

013   PRINT @(-1) : "ENTER YOUR BIRTHDAY:":

014   INPUT @(20,0) BIRTHDAY.INT "D"

015   TODAY.INT = DATE()

016   TODAY.EXT = OCONV(TODAY.INT,"D/")

017   MATPARSE TODAY FROM TODAY.EXT,"/"

018   BIRTHDAY.EXT = OCONV(BIRTHDAY.INT,"D/")

019   MATPARSE BIRTHDAY FROM BIRTHDAY.EXT,"/"

020   IF THIS.MONTH > BIRTH.MONTH THEN

021      INCREMENT = TRUE

022   END

023   IF (THIS.MONTH = BIRTH.MONTH OR THIS.DATE  BIRTH.DATE) THEN

024      INCREMENT = TRUE

025   END

026   IF INCREMENT THEN

027      THIS.YEAR += 1

028   END

029   AGE = THIS.YEAR - BIRTH.YEAR

030   NEXT.BIRTHDAY = BIRTH.MONTH : "/" : BIRTH.DATE : "/" : THIS.YEAR

031   NEXT.BIRTHDAY.INT = ICONV(NEXT.BIRTH-DAY,"D")

032   DAYS.TO.BIRTHDAY = NEXT.BIRTHDAY.INT - TODAY.INT

033   IF DAYS.TO.BIRTHDAY = 0 THEN

034      PRINT

035      PRINT "HAPPY BIRTHDAY!"

036      PRINT "TODAY, " : TODAY.EXT : ", YOU ARE " : AGE : " YEARS OLD"

037   END ELSE

038      PRINT

039      PRINT "ON ":NEXT.BIRTHDAY:", IN ": DAYS.TO.BIRTHDAY :" DAYS,":

040      PRINT " YOU WILL BE ":AGE:" YEARS OLD."

041   END

042 STOP

043 END

 

*

At first glance, it is obvious that the problem lies in the variable THIS.YEAR: THIS.YEAR is being incremented when it should not be. Before you start editing the program, however, use the Debugger to confirm your suspicions.

Using Breakpoints and Trace Variables

To examine the value of THIS.YEAR at the end of the program, the user needs to set up a breakpoint so that variables can be examined before the program ends. A breakpoint condition is a condition that invokes the Debugger whenever it is true.

The B command is used to assign a breakpoint condition. You can choose to break when the THIS.YEAR variable is equal to 1990.

*BTHIS.YEAR=1990<ENTER> +

The breakpoint condition says to transfer into the Debugger when the variable THIS.YEAR is equal to 1990. The plus sign (+) is printed after pressing the ENTER key to signify that the breakpoint was accepted into the breakpoint table.

Enter THIS.YEAR as a trace variable. A trace variable is a variable that is printed whenever a breakpoint is encountered. Enter it into the trace table with the T command:

*TTHIS.YEAR<ENTER> +

Add to the trace table the variables THIS.MONTH, BIRTH.MONTH, THIS.DATE, and BIRTH.DATE. It is suspected that the problem may be that these variables are not being assigned correctly.

*TTHIS.MONTH<ENTER> +

*TBIRTH.MONTH<ENTER> +

*TTHIS.DATE<ENTER> +

*TBIRTH.DATE<ENTER> +

To display the breakpoint and trace tables, use the D command:

*D

T1 THIS.YEAR

T2 THIS.MONTH

T3 BIRTH.MONTH

T4 THIS.DATE

T5 BIRTH.DATE

T6

B1 THIS.YEAR=1990

B2

B3

B4

 

*

The G command continues execution of the program.

*G<ENTER>

The screen clears and the prompt is printed. Type 9/3/61 and press ENTER:

ENTER YOUR BIRTHDAY: 9/3/61

The program halts when the breakpoint is reached.

ENTER YOUR BIRTHDAY: 3 SEP 1961

*B1 28       END

THIS.YEAR 1990

THIS.MONTH 07

BIRTH.MONTH 09

THIS.DATE 20

BIRTH.DATE 03

*

As expected, the condition is true after line 27 has been executed. The message B1 28 means that item 1 on the breakpoint table caused the break, and the line about to be executed is line 28. (The actual text of that line is displayed in half-intensity on the terminal screen.) The current values of the trace variables are printed.

Displaying and Changing a Variable

The error in the program becomes increasingly obvious as you continue in the Debugger. Since THIS.MONTH, BIRTH.MONTH, THIS.DATE, and BIRTH.DATE contain the correct data, the problem is in the way they are being compared. For THIS.MONTH to be incremented, the INCREMENT variable must be true. Confirm this by using the / command to print out the current value of INCREMENT:

*/INCREMENT

When ENTER is pressed, the value of INCREMENT is displayed, and you are given the opportunity to change its value.

*/INCREMENT<ENTER> 1=_

Type 0 as the new value for INCREMENT and press ENTER.

*/INCREMENT<ENTER> 1=0<ENTER>

 

*

Reset the value of THIS.YEAR to 1989.

*/THIS.YEAR<ENTER> 1990=1989<ENTER>

 

*

Using Execution Steps

To find out which comparison is failing, step through the crucial lines of the program this time around to see what exactly is happening. To begin the program executing again after line 19 with an execution step of 1 (an execution step is a number of lines that should be executed before returning to the Debugger). The E command should be used to specify the execution step:

*E1

Add the variable INCREMENT to the trace table.

*TINCREMENT<ENTER>+

The G command continues execution after line 19. One line executes and the program returns to the Debugger. The line about to be executed will be printed on the screen, along with any trace variables.

*G19<ENTER>

*E20       IF THIS.MONTH > BIRTH.MONTH THEN

THIS.YEAR 1989

THIS.MONTH 07

BIRTH.MONTH 09

THIS.DATE 20

BIRTH.DATE 03

INCREMENT 0

*

Step through 3 more times, until you find that the INCREMENT variable has been changed.

*G

*E25       END

THIS.YEAR 1989

THIS.MONTH 07

BIRTH.MONTH 09

THIS.DATE 20

BIRTH.DATE 03

INCREMENT 1

*

By stepping through the program, you will see that the INCREMENT variable is changed immediately before line 25. List lines 23 through 25 with the L command:

*L23-25

023   IF (THIS.MONTH = BIRTH.MONTH OR THIS.DATE > BIRTH.DATE) THEN

024      INCREMENT = TRUE

025   END

*

The problem is in the conditional for the IF statement. It becomes obvious that, as usual, the bug in the program is a simple logical error: the OR in line 23 should be an AND. With that simple edit, the program should run correctly.

Exit the Debugger with the END command, edit the source item, and recompile. The output now reads:

ENTER YOUR BIRTHDAY: 3 SEP 1961

ON  09/03/1989, IN 45 DAYS, YOU WILL BE 28 YEARS OLD.

 

>

Assigning New Values for Testing

It seems as if the bug is gone, for now. However, you are not confident that the program will still behave correctly at the end of the year. Using the Debugger, you can change the value of the variable TODAY.INT in the program and see whether the program still works.

Run the program again with the D option, use the T command to turn trace on, and set a breakpoint to stop executing before line 16. (The $ symbol on the breakpoint table represents the current line number.) Then continue execution with the G command.

>RUN BP BIRTHDAY (D)

 

*E1

*T<ENTER>

*B$=16<ENTER> +

*G<ENTER>

You will be prompted for a birthday. After entering a date, press ENTER. The program will halt before executing line 16.

ENTER YOUR BIRTHDAY  03 SEP 1961

*B1 16 TODAY.EXT = OCONV(TODAY.INT,”D/”)

*

Before line 16 is executed, reassign the value of the TODAY.INT variable with the / command. Then type the G command to continue execution.

*/TODAY.INT<ENTER>  7872=8036<ENTER>

 

*G<ENTER>

8036 is the internal value of December 31, 1989 and the program runs successfully:

ON 09/03/1989, IN 246 DAYS, YOU WILL BE 29 YEARS OLD.

>

Now that you have an idea of what the Debugger can do and why you would use it, you can go over the specifics of its operation.

See Also

Using the mvBASIC Debugger

Debugger Commands: Quick Reference

Fixing a Bug

Entering the Debugger

Exiting the Debugger

Displaying and Changing a Variable

Accessing Source Code

Using Breakpoints and Tracing

Using Execution Control

Printing Output

Using the Return Stack