[Rd] Am I missing something about debugging?

Mark.Bravington at csiro.au Mark.Bravington at csiro.au
Thu Jan 4 07:06:49 CET 2007

It is possible to do some of these things with the 'debug' package-- the
article in R-news 2003 #3 shows a few of the tricks. Suppose 'b1' calls
'c1'. If 'c1' exists as "permanent" function defined outside 'b1' (which
I generally prefer, for clarity), then you can call 'mtrace( c1)' and
'c1' will be invoked whenever it's called-- you don't have to first
'mtrace' 'b1' and then manually call 'mtrace(c1)' while inside 'b1'.

Even if 'c1' is defined inside the body of 'b1', you can get something
similar by using conditional breakpoints, like this

> mtrace( b1)
> # whatever you type to get 'b1' going
D(17)> # now look at the code window for 'b1' and find the line just
after the definition of 'c1'
D(17)> # ... say that's on line 11
D(17)> bp( 11, {mtrace( c1);FALSE})
# which will auto-mtrace 'c1' without stopping; of course you could
hardwire this in the code of 'b1' too

the point is that you can stick all sorts of code inside a conditional
breakpoint to do other things-- if the expression returns FALSE then the
breakpoint won't be triggered, but the side-effects will still happen.
You can also use conditional breakpoints and 'skip' command to patch
code on-the-fly, but I generally find it's too much trouble.

Note also the trick of 
D(17)> bp(1,F) 

which is useful if 'b1' will be called again within the lifetime of the
current top-level expression and you actually don't want to stop.

The point about context is subtle because of R's scoping rules-- should
one look at lexical scope, or at things defined in calling functions?
The former happens by default in the 'debug' package (ie if you type the
name of something that can be "seen" from the current function, then the
debugger will find it, even if it's not defined in the current frame).
For the latter, though, if you are currently "inside" c1, then one way
to do it is to use 'sys.parent()' or 'sys.parent(2)' or whatever to
figure out the frame number of the "context" you want, then you could do

D(18)> sp <- sys.frame( sys.parent( 2))
D(18)> evalq( ls(), sp)

etc which is not too bad. It's worth experimenting with sys.call etc
while inside my debugger, too-- I have gone to some lengths to try to
ensure that those functions work the way that might be expected (even
though they actually don't... long story).

If you are 'mtrace'ing one of the calling functions as well, then you
can also look at the frame numbers in the code windows to work out where
to 'evalq'.

The current 'debug' package doesn't include a "watch window" (even
though it's something I rely on heavily in Delphi, my main other
language) mainly because R can get stuck figuring out what to display in
that window. It's not that hard to do (I used ot have one in the Splus
version of my debugger) and I might add one in future if demand is high
enough. It would help if there was some way to "time-out" a
calculation-- e.g. a 'time.try' function a la

  result <- time.try( { do.some.big.calculation}, 0.05)

which would return an object of class "too-slow" if the calculation
takes more than 0.05s.

I'm certainly willing to consider adding other features to the 'debug'
package if they are easy enough and demand is high enough! [And if I
have time, which I mostly don't :( ]

Hope this is of some use


Mark Bravington
CSIRO Mathematical & Information Sciences
Marine Laboratory
Castray Esplanade
Hobart 7001

ph (+61) 3 6232 5118
fax (+61) 3 6232 5012
mob (+61) 438 315 623

> -----Original Message-----
> From: r-devel-bounces at r-project.org 
> [mailto:r-devel-bounces at r-project.org] On Behalf Of Ross Boylan
> Sent: Wednesday, 3 January 2007 9:09 AM
> To: R Development List
> Subject: [Rd] Am I missing something about debugging?
> I would like to be able to trace execution into calls below 
> the current function, or to follow execution as calls return. 
>  This is roughly the distinction between "step" and "next" in 
> many debuggers.
> I would also like to be able to switch to a location further 
> up the call stack than the location at which I enter the 
> debugger, to see the context of the current operations.
> Are there ways to do these things with the R debugger?  I've 
> studied the man pages and FAQ's, and looked at the debug 
> package, but I don't see a way except for manually calling 
> debug on the function that is about to be called if I want to 
> descend.  That's quite awkward, particularly since it must be 
> manually undone (the debug package may be better on that 
> score).  I'm also not entirely sure that such recursion 
> (essentially, debugging within the debugger) is OK.
> I tried looking up the stack with things like sys.calls(), 
> from within the browser, but they operated as if I were at 
> the top level (e.g.,
> sys.function(-1) gets an error that it can't go there).  I 
> was doing this in ess, and there's some chance the "can't 
> write .Last.value" error (wording approximate) cause by 
> having an old version is screwing things up).
> Since R is interpreted I would expect debugging to be a snap, 
> but these limitations make me suspect there is something 
> about the language design that makes implementing these 
> facilities hard.  For example, the browser as documented in 
> the Green book has up and down functions to change the frame 
> (p. 265); these are conspicuously absent in R.
> -- 
> Ross Boylan                                      wk:  (415) 514-8146
> 185 Berry St #5700                               ross at biostat.ucsf.edu
> Dept of Epidemiology and Biostatistics           fax: (415) 514-8150
> University of California, San Francisco
> San Francisco, CA 94107-1739                     hm:  (415) 550-1062
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel

More information about the R-devel mailing list