| **Navigation:**  [[welcome to my product .htm|User's Guide and Tutorials]] > Advanced Topics > The Debugger >====== Debugger Lesson ====== | [[using the clarion debugger.htm|{{btn_prev_n.gif|Previous page}}]][[welcome to my product .htm|{{btn_home_n.gif|Return to chapter overview}}]][[debugger options.htm|{{btn_next_n.gif|Next page}}]] | | || Clarion ships with a standalone 32-bit debugger; //Cladb.exe//. In Windows there exists the concept of a system "debugger". When you install the Clarion debugger as the system debugger, it uses the API function DebugActiveProcess() to connect to the process that caused the debugger to execute. __**Lesson**__ {{notebox.jpg|NoteBox.jpg}} This lesson uses the ABC Template chain. You must register these templates (ABCHAIN.TPL) before starting the lesson. **Prepare Your Program for Debugging** In this Lesson you will debug the Orders application, installed by default as //'\Lessons\Debugger\Orders.APP//. We have deliberately created a bug in this application. To begin, start Clarion and open the Orders application. In Windows XP, the Lessons folder is found in: **C:\Documents and Settings\All Users\Documents\SoftVelocity\Clarion7\Lessons** In Vista and Windows 7: **C:\Users\Public\Documents\SoftVelocity\Clarion7\Lessons** To debug your program with the debugger, you must tell the compiler to generate debug information. Use the **Project Editor** to establish this setting. (32-bit with debug information). 1.Open the //Orders// application with Clarion. 2.From the IDE menu, choose **Project** {{blttria.jpg|BLTTRIA.jpg}} **Project Options** to open the **Project Properties**. 3.Verify that the **Configuration** drop down list is set to //Debug//. 4.On the **Compiling** tab, select //Full// from the **Debug Mode** drop-down list. 5.Close the //Project Properties// dialog and **Save** your project changes if needed. **Identify the Bug** We have deliberately created a bug in the Orders application. To see it: 1.Set the Build Version to Debug (Choose **Build** {{blttria.jpg|BLTTRIA.jpg}} **Set Configuration** {{blttria.jpg|BLTTRIA.jpg}} **Debug**) 2.Press the {{runbut.jpg|RunBut.jpg}} button to make and run the Orders program. 3.From the Orders program menu, choose **Browse** {{blttria.jpg|BLTTRIA.jpg}} **Browse Customer Information File**. {{debug1.jpg|debug1.jpg}} This opens the customer list. 4.With the customer list open, //and using your mouse//, highlight a customer in the middle of the list and click the down arrow button at the bottom of the scroll bar {{scrdwn.jpg|scrdwn.jpg}} to scroll down one row. The list scrolls up! Using the arrow keys, the down arrow does nothing. Page Up, Page Down, Ctrl + Page Up, Ctrl + Page Down all work as expected. You've identified the bug: it is in the //BrowseCustomer// procedure and it only occurs when scrolling down. 5.Close (exit) the Orders program. The Clarion environment gains focus. **Start the Debugger** To start the debugger: 1.From the Clarion environment, press the {{debugbut.jpg|debugbut.jpg}} button to start the debugger. You may want to shut down other applications to conserve resources because you will be running the Clarion environment, the debugger, plus the Orders program in addition to any others. {{tipbox.jpg|TipBox.jpg}} You can run the debugger independent of the development environment to save even more resources: run Cladb.EXE. When you invoke the debugger, the Clarion IDE will re-make the project if needed, and then run the degugger. The debugger opens the //Globals// window, the //Procedures// window, the //Stack Trace (local variables)// window, and a starting source file. {{debug2.jpg|debug2.jpg}} The debugger also opens the Trace window and the Disassembly window in the iconized state. **Arrange the Debugger Windows** All of the debugger windows are movable and resizable. So you should arrange the windows so that they are easy for you to work with. 1.Maximize the debugger. You will usually want to see several debugger windows at once, so you need as much screen space as possible. 2.In the //Procedures// window, click BROWSECUSTOMER to open the source window for the //BrowseCustomer// procedure. {{debug3.jpg|debug3.jpg}} The debugger opens a source code window for ORDER002.CLW, the source module containing the //BrowseCustomer// procedure. {{tipbox.jpg|TipBox.jpg}} CLICK on the procedure or module headers to sort the respective columns in ascending order. The Procedures window shows all the procedures and routines for the program you are debugging. CLICK on any procedure to see the source code for that procedure. 3.Reposition and resize the windows so they are easy for you to work with. We recommend a layout that shows lots of source code, shows as many local variables as possible (in the Stack Trace window), and a watch window. You will need to adjust these windows according to your tastes. {{debug4.jpg|debug4.jpg}} **Setting BreakPoints** A breakpoint tells the debugger that an application should break (pause execution) at a certain point. Breakpoints allow you to suspend execution where and when you need to. Rather than stepping through your code line-by-line or instruction-by-instruction, you can allow your program to run until it hits a breakpoint, then start to debug. This speeds up the debugging process enormously. You want to suspend (or break) the program at the point the bug occurs, and then look for the cause of the problem, usually in the form of incorrect variable values or incorrect execution sequence. Recall the bug is associated with scrolling downward. To set the breakpoint: 1.CLICK on the //ORDER002.CLW// window to give it focus. 2.Press the **F** key to open the Search for dialog. {{tipbox.jpg|TipBox.jpg}} A right-click on the source code window displays a popup menu of all the source window functions and their keyboard shortcuts. 3.In the **Search for** dialog, enter //scrollone//, and then press the **OK** button. You will land on the ScrollOne method declared for the BRW1 class. Press the **A** key to find //scrollone// again. This time, you land on the label for the code of this method. {{debug5.jpg|debug5.jpg}} This method is a likely location for the breakpoint you need. {{tipbox.jpg|TipBox.jpg}} Searching is not case sensitive. 4.CLICK on the first executable statement after the code statement: **IF LOC:Flag** {{notebox.jpg|NoteBox.jpg}} Although you can set a breakpoint on routine and method labels, you may get unexpected results. We recommend setting breakpoints only on executable statements. 5.Press the **B** button in the lower right section of the source window or press the **B** key to set a breakpoint on this statement. You may also right-click and select **Set Breakpoint** from the popup menu. Or you may double-click the line. If you repeat any of these actions on the same line, it will clear the breakpoint. The debugger displays breakpoints in red; however, because this is also the currently selected line (green), the breakpoint appears yellow until you move off the current line. **Debug the Program** The debugger is now set to suspend program execution at the first statement in the BRW1.ScrollOne method. To debug the program: 1.Press the **G** button or press the //G// key to start the Orders program. The Orders program begins execution. Its main window opens on top of the debugger. 2.Choose **Browse** {{blttria.jpg|BLTTRIA.jpg}} **Browse Customer** Information file. This opens the customer browse list. 3.With the customer list open, select a customer halfway down the list and click on the down arrow button {{scrdwn.jpg|scrdwn.jpg}} to scroll down one row. The debugger detects the breakpoint, suspends the Orders program, and displays the breakpoint statement (with a yellow background). 4.Click on the Source window to give it focus, and click on the **T** button (or press the //T// key) to execute the next statement. The debugger executes a single statement, then displays the next source statement to execute with a green background. 5.Repeat step 4 until after the **PARENT.ScrollOne(Event)** executes. This calls an ABC method, BrowseClass.ScrollOne in ABBROWSE.CLW: **BrowseClass.ScrollOne PROCEDURE(SIGNED Ev)** **  CODE** **  SELF.CurrentEvent = Ev** **  IF Ev = Event:ScrollUp AND SELF.CurrentChoice > 1** **    SELF.CurrentChoice -= 1** **  ELSIF Ev = Event:ScrollDown AND |** **             SELF.CurrentChoice <; SELF.ListQueue.Records()** **    SELF.CurrentChoice += 1** **  ELSIF ~SELF.FileLoaded** **    SELF.ItemsToFill = 1** **    SELF.Fetch(CHOOSE(Ev = EVENT:ScrollUp,1,2))** **  END** When you step through this method, only the first condition executes causing the current choice to move up one line. **Examine Variable Values** You can surmise that the above IF condition must be true in order for the customer list to scroll //up// one row, and the ELSIF condition must be true in order for the customer list to scroll //down// one row. You can examine (and modify) the values of the variables within the ELSIF condition to test this theory'EVENT:ScrollUp must be the event passed to this method. Also, SELF.CurrentChoice is greater than one, meaning the highlight row is not the first in the list box. To examine and edit the variable values: 1.Press the **G** button or press the //G// key to continue executing the Orders program. **The Orders program gains focus and continues execution where it left off.** 2.Again, click on the down arrow button to scroll down one row. Again, the debugger detects the breakpoint, suspends the Orders program, and displays the breakpoint statement. 3.CLICK in the //Stack Trace// window, or choose **Window** {{blttria.jpg|BLTTRIA.jpg}} **Stack Trace,** or restore the minimized //Stack Trace// window. {{debug6.jpg|debug6.jpg}} 4.In the //Stack Trace// window, RIGHT-CLICK on the //EVENT// variable. This shows a popup menu. Select Watch Variable. A new window appears labeled //Watch//. Add the //LOC:Flag// variable in the same manner. The watch window shows the label of the variable on the left and its value on the right. The value of //EVENT// is 4. The value of //LOC:Flag// is currently 3. You can surmise that //EVENT// is getting the wrong value from //LOC:Flag//. In the next section, we'll test this theory by changing the value of //LOC:Flag// to a different number, for example, 4. **Edit Variable Values** 1.In the //Stack Trace// window, RIGHT-CLICK on //LOC:Flag//, then choose **Edit variable** to open the //Edit// dialog. 2.In the //Edit// dialog, enter 4, then press **OK**. The debugger changes the value of //LOC:Flag// to 4. Now you can continue execution of the Orders program to see if it scrolls properly. 3.With focus in the Source window, press the **T** button or press the //T// key to execute the next statement. The debugger displays the next source statement to execute with a green background. 4.Repeat step 3 until the first statement in the BrowseClass.ScrollOne method executes. Notice that the ELSIF conditional statements now executes. This is because the ELSIF condition is now true: //Ev// is equal to EVENT:ScrollDown, and the highlighted row is less than SELF.ListQueue.Records. 5.Press the **G** button or press the //G// key to continue executing the Orders program. **The Orders program continues execution where it left off.** This time, the customer list scrolls correctly! This confirms the theory that //EVENT// contains an incorrect value at this point in the program. **Examine Global Variable Values** Often you will want to examine global variables, record buffer values, and the values of Clarion's built-in "Library State functions (ACCEPTED(), EVENT(), ERRORCODE(), etc.). To examine and edit these global variable values: 1.Again, press the down arrow key to scroll down one row. Again, the debugger detects the breakpoint and suspends the Orders program. 2.CLICK in the //Globals// window, or choose **Window** {{blttria.jpg|BLTTRIA.jpg}} **Globals**. 3.In the Globals window, click on the ( + ) beside ORDERS (near the bottom of the Globals list) to expand the list of global variables for the ORDERS module. 4.In the Globals window, click on the ( + ) beside CUSTOMER$CUST:RECORD to expand the list of customer record buffer fields. 5.In the Globals window, click on the ( + ) beside CUST:CONTACT to see the value of each byte in the CUST:CONTACT field. {{debug8.jpg|debug8.jpg}} The //Globals// window shows global variables, record buffers, and Library States. The labels are on the left and the values are on the right. You may also edit global variables the same way you edited local variables. **Watch Selected Variables** The Watch window lets you pick specific variables (local, global, or both) and "Library States" to monitor during the debugging process. That is, rather than searching through the //Stack Trace// window and the //Globals// window with each debugging cycle, you can add the variables to the Watch window and examine all the pertinent values in one place. To place variables in the Watch window: 1.In the //Stack Trace// window or the //Globals// Window, RIGHT-CLICK on an item (variable or Library State), then choose **Watch variable**. **This opens the Watch window and places the selected item in the window.** {{debug10.jpg|debug10.jpg}} 2.Repeat step **//1//** for all the pertinent variables and Library States. **Close the Debugger** 1.In the debugger, choose **File** {{blttria.jpg|BLTTRIA.jpg}} **Exit**. The debugger automatically shuts down the debuggee (the Orders program) too.