Debugging in R using debug(), browser() and trace()

Overview
Marking a function for debugging
Commands while debugging
Unmarking a function
Conditional breakpoints using browser()

Overview

The browser() function in R's base package allows you to single step through the execution of an R function. You can view and change objects during execution. There is support for setting conditional breakpoints.

The debug() function marks a function for debugging, so that browser() will be called on entry. Use ?debug in R to see the man page for debug().

The trace() function modifies a function to allow debug code to be temporarily inserted. Use ?trace in R to see the man page for trace().

The findLineNum() and setBreakpoint() functions in the utils package work with line number references to compute locations for calls to trace().

Further details are given in the R Language manual in the Debugging chapter, and in Roger Peng's "An Introduction to the Interactive Debugging Tools in R".


Marking a function for debugging

debug() works by marking functions for debugging. When R starts to evaluate such a function, the evaluator automatically breaks to the debugger.

Use debug(fun) to mark a function for debugging. This marks the body of the function, so if you make any changes to it (e.g. using fix(fun), or by source()'ing it from a file), the mark goes away. On the other hand, if you copy the function to another object, the new object is marked for debugging as well.

Alternatively, trace(fun, ...) can set a variety of different debugging options within the function. The default trace(fun) will print a line each time fun() is called. For behaviour similar to debug(fun), use trace(fun, tracer=browser). See ?trace for other options.

The setBreakpoint() function provides a front end to trace() for the case where the function contains source reference information. (By default source() inserts this information, but packages are normally built without it.) For example, if fun() was sourced from the file fun.R, a breakpoint can be set in the code from line 20 of that file using setBreakpoint("fun.R#20"). The default tracer is browser(), but other tracers can be set.


Commands while debugging

When the debugger is invoked, you are left in a browser(). Expressions typed at the prompt are evaluated in the local environment. The following commands are available.
<RET>
Go to the next statement if the function is being debugged. Continue execution if the browser was invoked.
c or cont
Continue execution without single stepping.
n
Execute the next statement in the function. This works from the browser as well.
where
Show the call stack.
Q
Halt execution and jump to the top-level immediately.
To view the value of a variable whose name matches one of these commands, use the print() function, e.g. print(n).

Here is a sample session, based on the one in the R Language manual.

> debug(mean.default)
> mean(1:10)
debugging in: mean.default(1:10)
debug: {
    if (na.rm)
        x <- x[!is.na(x)]
    trim <- trim[1]
    n <- length(c(x, recursive = TRUE))
    if (trim > 0) {
        if (trim >= 0.5)
            return(median(x, na.rm = FALSE))
        lo <- floor(n * trim) + 1
        hi <- n + 1 - lo
        x <- sort(x, partial = unique(c(lo, hi)))[lo:hi]
        n <- hi - lo + 1
    }
    sum(x)/n
}
Browse[1]> where
where 1: mean.default(1:10)
where 2: mean(1:10)

Browse[1]>
debug: if (na.rm) x <- x[!is.na(x)]
Browse[1]>
debug: trim <- trim[1]
Browse[1]> trim
[1] 0
Browse[1]>
debug: n <- length(c(x, recursive = TRUE))
Browse[1]> c
exiting from: mean.default(1:10)
[1] 5.5

Unmarking a function

Call undebug(fun) to remove the debugging flag from a function. Most changes to the body of a function will also remove this flag, for instance using fix(fun) or calling source() to recreate the function.

Call untrace(fun) to remove the tracing code from a function.


Conditional breakpoints using browser()

debug() has no commands to set conditional breakpoints, but trace() can include conditional expressions in the tracer argument. For example, trace(fun, quote(if (x > 10) browser())) will stop if x (presumably an argument to fun()) is bigger than 10.

Explicit calls to browser() in a function will invoke the browser, causing execution of a function to pause. These can be wrapped in conditional code when the function is written. This is almost the same as if the function had been flagged using debug(fun); the difference is that the <RET> key acts like a c to continue execution, not like an n to execute a single line.


Last modified: Sat 20 Mar 2010, by Duncan Murdoch