debug-package {debug}R Documentation

How to use the debug package

Description

debug is an alternative to trace and browser, offering:

Even if you don't write functions, or even if you don't write buggy functions, you may find it helpful to run the debugger on functions in package:base or other packages. Watching what actually happens while a function is executing, can be much more informative than staring at a piece of code or terse documentation.

Debugging your function f is a two-stage process. First, call mtrace(f) to store debugging information on f, and to overwrite f with a debug-ready version that will call the debugger itself. Second, do whatever you normally do at the command prompt to invoke f. This is often a direct call to'f', but can be any command that eventually results in f being invoked. [The third, fourth, etc. stages, in which you actually fix the problem, are not covered here!]

When f is invoked, a window will appear at the bottom of the screen, showing the code of f with a highlight on the first numbered line. (There is also an asterisk in the far left hand column of the same row, showing that there's a breakpoint.) The command prompt in R will change to "D(...)> ", showing that you are "inside" a function that is being debugged. The debugger is now in "step mode". Anything you type will be evaluated in the frame of the function– this includes assignments and creation of new variables. If you just type <ENTER>, the highlighted statement in f will be executed. The result of the statement will be printed in the R command window, and the highlight will (probably) move in the f code window.

To progress through the code of f, you can keep pressing <ENTER>, but you can also type go() to put the debugger into "go mode", whereupon it will keep executing code statements without manual intervention. In "go mode", nothing will be printed in the command window (except if there are cat or print calls in the function code) until either:

In the first case, control is returned to the normal R command prompt, just as if the debugger had not been used. In the other cases, the D(...)> prompt will return and the line that caused the error/interrupt (or that has the breakpoint) will be highlighted in the code window. You are then back in step mode. If there was an error, you can type statement(s) that will cause the error not to happen when the highlighted line executes again, or you can move the highlighted execution point to another line number by calling skip. Execution carries on quite normally after errors, just as if the offending statement had been wrapped in a try call. If your function eventually exits normally (i.e. not via qqq(), as described next), it will be as if the error never happened (though the error message(s) will be displayed when the R command prompt returns).

When in step mode, you can finish debugging and return to the normal R command prompt by typing qqq(). <ESC> also seems to work, but qqq() is probably safer. If you type <ESC> while in go mode, you will usually be returned to step mode, but sometimes to the R command prompt (e.g. if you happen to press it while debug is executing its own code rather than yours– this is on the to-do list), and sometimes there will be no immediate effect (e.g. if C code is running).

Breakpoints, including conditional breakpoints, are set and cleared by bp. Calling go(n) puts the debugger into go mode, but also sets a temporary breakpoint at line n, which will be triggered the first time execution reaches line n but not subsequently.

When the main function code has completed, the debugger moves into any on.exit code, which is also displayed and line-numbered in the code window. (Even if there are no calls to on.exit, a numbered NULL statement is placed in the exit code section, so that you can always set a "run-until-function-finishes" breakpoint.) If you exit via qqq(), the exit code will not be executed first; this can lead to subsequent trouble with open connections, screwed-up par values in graphics, etc.. To make sure the exit code does get executed:

When you want to restore f to its normal non-debugging state (and you are back at the real R command prompt), type mtrace(f,FALSE). To restore all debuggees, type mtrace.off(). It is advisable not to save functions in an mtraced state; to avoid manual untracing and retracing, look up Save in package mvbutils.

You can debug several functions "at once" (e.g. if f calls g, you can mtrace both f and g, with mtrace(g) called either inside or outside the debugger), causing several code windows to be open simultaneously. If f is called again inside f (either via some statement in f, or from something you type in step mode), another f code window will open. The number in the window title is the frame number, and the currently-active frame number is shown in the D(...)> prompt.

For statements typed in at the D(...)> prompt, only the first syntactically-complete R expression will be executed; thus, typing a <- 1; a <- 2 will set a to 1, but typing { a <- 1; a <- 2} will set a to 2.

S3 methods work fine with mtrace, but S4 methods don't unless you do something special. My suspicion is that they will work OK if you can somehow pass the true name of the method to mtrace, along with its environment using the from argument. This is probably fixable, but low priority (unless I get lots of requests); I have no plans to write S4 methods, and hope not to have to debug other people's!

For further information, see R-news 3/3.

Options

Command recall is ON by default, but this means that anything typed while debugging will also be seen in history() after leaving the debugger. If this is a problem, set options( debug.command.recall=FALSE) (probably in .First).

In step mode, only objects with object.size < 8192 bytes will be printed in full by default; for larger objects, a summary is given instead. You can force printing of any individual object via print, but you can also increase (or decrease) the threshold to X bytes, by setting options( threshold.debug.autoprint.size=X).

Various TCL/TK-related aspects of the code window can be altered:

Note

Display bugs: There have been sporadic and unreproduceable display problems with the TCL/TK window; sometimes the window frame will appear, but with garbled contents or no contents at all. With RTERM in MS-Windows, a couple of ALT-TABs and mouse clicks to change focus are sometimes necessary. In extremis, the window will eventually sort itself out if you manually minimize, maximize, and restore it– admittedly an irritation. Although the problem seems less frequent these days, I'm not convinced it is fully solved.

If you encounter this problem, try setting options(shakeup.debug.windows=TRUE) (also in .First). The price paid for setting this option, is that window focus will switch away from R to the new code window when the latter is first created, which is mildly irritating. On MS-Windows, I have a fix for that too, but it requires a DLL written in Delphi not C, so I can't CRAN it; let me know if you are desperate.

For ESS users: I'm not an Emacs user and so haven't tried ESS with the debug package myself, but a read-through of the ESS documentation suggests that at least one ESS variable may need changing to get the two working optimally, as shown below. Please check the ESS documentation for further details on these points (and see also README.mvbutils in the mvbutils package). I will update this helpfile when I have more info on what works.

Author(s)

Mark Bravington

See Also

mtrace, go, skip, qqq, bp, get.retval, mtrace.off, check.for.tracees


[Package debug version 1.2.0 Index]