Learn R Programming

debug (version 1.0.1)

README.debug: How to use the debug package

Description

For how to use the debug package, see DETAILS.

Usage

README.debug() # shows this documentation

Arguments

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:
  • tab.widthdefaults to 4, for indenting code lines (not related to TCL/TK)
  • debug.fontdefaults to "Courier"; try e.g. ="Courier 24 italic"
  • debug.height(in lines) defaults to 10
  • debug.width(in characters) defaults to 120
  • debug.screen.posdefaults to "+5-5" for BL corner; try "-5-5" for BR, "-5+5" for TR, "+5+5" for TL.

Details

debug is an alternative to trace and browser, offering:
  • a visible code window with line-numbered code and highlighted execution point;
  • the ability to set (conditional) breakpoints in advance, at any line number;
  • the opportunity to keep going after errors;
  • multiple debugging windows open at once (when one debuggee calls another, or itself);
  • full debugging ofon.exitcode;
  • the ability to move the execution point around without executing intervening statements;
  • direct interpretation of typed-in statements, as if they were in the function itself.
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. 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 Rwill 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 , the highlighted statement in f will be executed. The result of the statement will be printed in the Rcommand window, and the highlight will (probably) move in the f code window. To progress through the code of f, you can keep pressing , 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:
  • the function completes normally, or
  • an error occurs in the function, or
  • a breakpoint is triggered.
In the first case, control is returned to the normal Rcommand 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 (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 Rcommand prompt returns). When in step mode, you can finish debugging and return to the normal Rcommand prompt by typing qqq(). also seems to work, but qqq() is probably safer. If you type while in go mode, you will usually be returned to step mode, but sometimes to the Rcommand prompt, and sometimes there will be no 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:
  • useskipto move to the start of the exit code;
  • then usego(n)to run to the final NULL in the exit code;
  • then useqqq()to finish debugging.
When you want to restore f to its normal non-debugging state (and you are back at the real Rcommand prompt), type mtrace(f,FALSE). To restore all debuggees, type mtrace.off() (qv). 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 Rexpression 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 (probably fixable, but low priority; I have no plans to use them, and hope not to have to debug other people's!). For further information, see R-news 3/3.

See Also

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