Debugging MATLAB Programs
Use of the MATLAB Editor/Debugger as an M-file editor was discussed in Section 1.4 of Chapter 1. Figure 1.4-1 (in Chapter 1) shows the Editor/Debugger screen. Figure 4.7-1 shows the Debugger containing two programs to be analyzed. Here we discuss its use as a debugger. The Editor/Debugger menu bar contains the following items: File, Edit, Text, Cell, Tools, Debug, Desktop, Window, and Help.
The File, Edit, Desktop, Window, and Help menus are similar to those in the Desktop, with a few exceptions. For example, the File menu in the Editor/Debugger contains the item Source Control, a file management system for integrating files from different sources. This system is used by developers of very large programs. Another example is the item Go to Line on the Edit menu. Click on it and enter a line number in the dialog box, then click OK. This feature is useful for navigating through files with many lines. An additional example is the Help menu in the Editor/Debugger, which contains the specific help item Using the M-file Editor.
The Cell and Tools menus involve advanced topics that will not be treated in this text. The Desktop menu is similar to that in the Command window. It enables you to dock and undock windows, arrange the Editor window, and turn the Editor toolbar on and off.
Below the menu bar is the Editor/Debugger toolbar. It enables you to access several of the items in the menus with one click of the mouse. Hold the mouse cursor over a button on the toolbar to see its function. For example, clicking the button with the binoculars icon is equivalent to selecting Find and Replace from . }”. the Edit menu. One item on the toolbar that is not in the menus is the function button with the script f icon (f). Use this button to go to a particular function in the M-file. The list of functions that you will see includes only those functions whose function statements are in the program. The list does not include functions that are called from the M-file
At the far right of the toolbar is the Stack menu. Here we discuss the Text,
Debug, and Stack menus of the Editor/Debugger,
To create a new M-file in the MS Windows environment, in the Command window select New from the File menu, then select M-file. You will then see the Editor/Debugger window. You can use the keyboard and the Edit. menu in the Editor/debugger would most word processors to create and edit the file. Note that each line in the file is numbered on the left. When finished, select Save from the File menu in the Editor/Debugger. In the dialog box that appears, replace the default name provided (usually named Untitled) with the name example/, and click on Save. The Editor/Debugger will automatically provide the extension .m and save the file in the MATLAB current directory, which for now we will assume is on the hard drive.
To open an existing file, in the Command window select Open from the File menu. Type in the name of the file or use the browser to select it. The Editor/Debugger window then opens. Once in the Editor/Debugger you can open more than one file. If you do, each file has a tab at the bottom of the window. Click on a tab to make that file the active one for editing and debugging
The Text Menu
The Text menu supplements the Edit menu for creating M-files. With the Text menu you can insert or remove comments, increase or decrease the amount of indenting; turn on smart indenting, and evaluate and display the values of selected variables in the Command window. Click anywhere in a previously typed line, and then click Comment in the Text menu. This makes the entire line a comment. To turn a commented line into an executable line, click anywhere in the line, and then click Uncomment in the Text menu.
The Increase Indent and Decrease Indent items on the Text menu work in a similar way. Just click anywhere in a previously typed line, and then click Increase Indent or Decrease Indent to change the indentation of the line.
The Editor/Debugger automatically indents any lines typed after a conditional statement, a for statement, or a while statement, up to where you type the corresponding end statement. Use the Smart Indent item on the Text menu to start automatic indenting in a previously typed line and in any lines typed thereafter.
Click anywhere in the line, and then click Smart Indent in the Text menu.
Use the Evaluate Selection item in the Text menu to display the values of selected variables in the Command window. Highlight the variable in the file, and click on Evaluate Selection. The variable name and its value appear in the Command window. After highlighting the variable, you can also right-click and the Context menu will appear. Then select Evaluate Selection on this menu. A third way to evaluate the value of a variable is to go to the Command window and type its name; however, this process requires you to leave the Editor/Debugger window.
After the file has been executed you can view a variable’s value in Data tips, a window that appears when you position the cursor to the left of a variable. The variable’s value stays in view until you move the cursor. Data tips are always on in debug mode, but are off by default in edit mode. You can turn them on by using the Preferences choice under the File menu. You can also view values in the Array Editor. In the following discussion, when we say you .should “evaluate the variable,” you can use any of these methods.
The Debug Menu
Breakpoints are points in the file where execution stops temporarily so that you can examine the values of the variables up to that point. You set breakpoints with the Set/Clear Breakpoint item on the Debug menu. Use the Step, Step In, and Step Out items on the Debug menu to step through your file after you have set breakpoints and run the file. Click Step to watch the script execute one step at a time. Click Step In to step into the first executable line in a function being called. Click Step Out in a called function to run the rest of the function and then return
to the calling program.
The solid green arrow to the left of the line text indicates the next line to be executed. When this arrow changes to a hollow green arrow, MATLAB control is now in a function being called. Execution returns to the line with the solid green arrow after the function completes its operation. The arrow turns yellow at a line where execution pauses or where a function compfetes its operation. When the program pauses you can assign new values to a variable, using either the Command window or the Array Editor.
Click on the Go Until Cursor item to run the file until it reaches the line where the cursor is; this process sets a temporary breakpoint at the cursor. You can save and execute your program directly from the Debug menu if you want, by clicking on Run (or Save and Run if you have made changes). You need not set any breakpoints beforehand. Click Exit Debug Mode to return to normal editing. To save any changes you have made to the program, first exit the debug mode, and then save the file.
Most debugging sessions start by setting a breakpoint. A breakpoint stops M-file execution at a specified line and allows you to view or change values in the function’s workspace before resuming execution. To set a breakpoint, position the cursor in the line of text and click on the breakpoint icon in the toolbar or select Set/Clear Breakpoints from the Debug menu. You can also set a breakpoint by right-clicking on the line of text to bring up the Context menu and choose Set/Clear Breakpoint. A red circle next to a line indicates that a breakpoint is set at that line. If the line selected for a breakpoint is not an executable line, then the breakpoint is set at the next executable line. The Debug menu enables you to clear all the breakpoints (select Clear Breakpoints in All Files). The Debug
menu also lets you halt M-file execution if your code generates a warning, an error, or a NaN or Inf value (select Stop if Errors/Warnings).
The Stack Menu
MATLAB assigns each M-file function its own workspace, called the function workspace, which is separate
the base and function workspaces when debugging M-files by using the Stack; menu in the Editor/Debugger. The Stack menu is only available in debug mode; otherwise it is grayed out. The base workspace is the workspace used by the Command window.
Unless explicitly declared to be a global variable with the global command, all variables created in a function are local to that function. We think of the base workspace and the function workspaces as a “stack” of objects. Going up and STACK down the stack means going into and out of the various workspaces.
To set preferences for the Editor/Debugger, select Prefences from the file menu. This opens a dialog box with several items. Here we mention two useful items to keep in mind. Under the Display preferences item, you’ can choose to display or not display line numbers and Data tips.
Under Keyboard you can choose to have the Editor match parentheses while editing.
The Editor/Debugger is useful for correcting run time errors because it enables you to access function work spaces and examine or change the values they contain. We will now step you through an example debugging session. Although the example M-files are simpler than most MATLAB code, the debugging concepts
demonstrated here apply in general. First create an M-file called fun1. rn that accepts an input vector and returns the number of values in the vector that are above its average (mean) value. This file calls another M-file, fun2 .rn, that computes the number of values above the average, given the vector and its average.
function y = fun1(x)
avg = suro(x)/length(x);
y = fun2(avg,x);
Create the f un1, . m- file exactly as it is shown above, complete with a planted bug. Then create the file fun2 .rn, which is shown below.
function above = fun2(x,avg)
above = length(find(x>avg));
Use a simple test case that can be calculated by hand. For example, use the vector v = [1, 2, 3, 4, 10]. Its average is 4, and it contains one value(10) above the average. Now call the function fun1 to test it.
»above = fun1[l,2,3,4,1O])
The answer should be I,and therefore at least one of the functions, fun1 rn or fun2 .m,is working incorrectly. We. will use the Editor/Debugger graphical interface to isolate the error. You could also use the debugging functions from the Command window prompt. For information about these functions, use the Search tab in the Help Navigator to search for the phrase “functions for debugging.” If you have just created the M-files using the Editor/Debugger window, you can continue from this point. If you’ve created the M-files using an external text
/ editor, start the Editor/Debugger and then open both M-files. You will see two tabs at the bottom of the screen, named fun1.m and fun2 .m. Use these to switch between the two files. See Figure 4.7-1.
At this point you might find it convenient to close all windows on the Desktop except for the Command window, and then dock the Debugger windows for both fun1.rn and fun2 .min the Desktop (to do this, select Dock from the Debugger’s Desktop menu, once for each file). Then click on one of the tiling icons on the far right of the menu bar. Select the tiling pattern you want. Figure 4.7-1 shows the two functions split top to bottom. This displays the Command window and the two Editor/Debugger windows, one for fun1.m and one for fun2 .m. This
enables you to easily see the computation results in the Command window. Be sure to. reduce the width of the Command window so that you can see the Stack menu in the Editor/Debugger. If the Editor/Debugger is not docked, then you will have to switch back and forth between, the three windows (by clicking on the
desired window, or by pressing Alt and Tab simultaneously, for example).
At the beginning of the debugging session, you are not sure where the error is. A logical place to insert a breakpoint is after the computation of the average in fun1 .m. CW to the Editor/Debugger window for fun1 .m and set a breakpoint at line 3 (y = fun2 (avg , x )) by using the Set Breakpoint button on the toolbar. The line number is indicated at the left. Note that to evaluate the value of the variable avg, we must set a breakpoint in any line Lowing the line in which avg is computed.
To get to the breakpoint and check the values of interest, first execute the function from the Command window by typing fun1 ( [1, 2, 3, 4, 10]). When execution of an M-file pauses at a breakpoint, the green arrow to the left of the
text indicates the next line to be executed. Check the value of avg by highlighting the name of the variable, then right-clicking to bring up the Context menu, and choosing Evaluate Selection. You should now see avg = 4 displayed in the Command window. Because the value of avg is correct, the error must lie either in the function call to fun2 in line 3 in fun1. m, or in the fun2 .m file.
Note that the prompt has changed to K», which stands for “keyboard.” With this prompt you can enter commands in the Command window without disturbing the execution of the program. Suppose you find that the output of a function is incorrect. To continue debugging, you can enter the correct value for the variable at the K» prompt.
Use the Stack pull-down menu in the upper-right comer of the Debugger window to change workspaces. To see the base workspace contents, select Base Workspace from the Stack menu. Check the workspace contents using who or the graphical Workspace Browser. Any variables you may have created in the current session will show up in the listing. Note that the variables avg and x do not show up because they are local to the function fun1. Similarly, to see the contents of the workspace of fun1 .m,select fun1 from the Stack menu and type who in the Command window. You will see the local variables avg and x displayed.
Stepping through Code and Continuing Execution
Clear the breakpoint at line 3 in fun1 .m by placing the cursor on the line and clicking on the Clear Breakpoints button. (Or right-click on the line to bring up the Context ..menu and choose Set/Clear Breakpoint). Continue executing the M-file by clicking the Continue button on the Debugger’s toolbar. Open the fun2 .m file and set a breakpoint at line 2 to see if the correct values of x and avg are being passed to the function. In the Command window, type above = fun1 ( [1, 2, 3 , 4, 10] ) . Highlight the variable x in the expression above = length (find (x>avg) ) ; in line 2, right-click on it, and select Evaluate Selection from the Context menu. You should see x = 4 in the Command window. This value is incorrect because x should be [1, 2 , 3 , 4 , 10] .Now evaluate
the variable avg in line 2 the same way. You should see avg = [1, 2 , 3 , 4, 10] in the Command window. This is incorrect because avg should be 4.
So the values of x and avg have been reversed in the function call in line 3 of fun1 . m, This line should be y = fun2 (x , avg). Clear all breakpoints, exit the debug mode by selecting Exit Debug Mode on the Debug menu. Edit the line to correct the error, save the file, and run the test case again. You should get the correct answer.
Debugging a Loop
Loops such as for and while loops that do not execute the proper number of times are a common source of errors. The following function file invest . m, which has a planted bug, is intended to calculate how much money will be accumulated in a savings account that draws interest at the rate r percent compounded annually, if an amount x(k), k = 1,2,3, … is deposited at the end of year k (this amount is not included in the interest calculation for that year).
function z = invest(x,r)
z = 0;
y = 1 + O.O1*r;
for k = 1:length(y)
z = z *y + x (k ) ;
To check the function, use the following test case, which is easily computed by hand. Suppose we deposit $1000, $1500, and $2000 over three years, in a bank paying 10 percent interest. At the end of the first year the amount will be $1000; at the end of the second year it will be $1 000( 1.1) + $1500 = $2600, and at the end of the third year it will be $2600( 1.1) + $2000 = $4860. After creating and saving the function invest .m, call it in the Command window as follows:
»total = invest([1000,1500,2000],10)
which is incorrect (the answer should be 4860). To find the error, set a breakpoint at line 5 (the line containing the text z = z *y + x (k) i). Run the function from the Command window by typing total = invest ( [1000,1500,2000],
10) ). Execution stops at the breakpoint. Check the values of z, y, and k. These are z = 0, y = 1.1, and k = 1, which are correct. Next, select Step on the Debug menu. The green arrow moves to the line containing the end statement. Check the values. They are z == 1000 and k = 1, which are correct. Select Step one more time, and again check the values of z and k. They are still z = 100 a and k = 1, which are correct. Finally, select Step again, and check the values. You should see the following in the Command window.
K» z??? Undefined function or variable ‘Z’.
K» k??? Undefined function or variable ‘k’.
Therefore, the program has gone through the loop only once, instead of three times. The error is in the upper limit of k, which should be length (x), not length (y).