Recommendations for "dynamic / interactive" function debugging in R?

When debugging a function, I usually use

library(debug) mtrace(FunctionName) FunctionName(...) 

And it works well for me.

However, sometimes I try to debug a complex function that I do not know. In this case, I may find that there is another function inside this function that I would like to โ€œenterโ€ (โ€œdebugโ€) in order to better understand how the whole process works.

So one way to do this is:

 library(debug) mtrace(FunctionName) FunctionName(...) # when finding a function I want to debug inside the function, run again: mtrace(FunctionName.SubFunction) 

The question is, is there a better / smarter way to do interactive debugging (as I already described), what can I skip?

ps: I know that where various questions are asked about this in SO (see here ). However, I could not find a similar question / solution to what I asked here.

+6
debugging r
source share
3 answers

Not quite sure about the use, but when you encounter a problem, you can call the traceback() function. This will show the path of your function call through the stack until it encounters its problem. You could, if you were inclined to work from top to bottom, call debug on each of the functions listed in the list before calling the function. Then you will go through the whole process from the very beginning.

Here is an example of how you could do this in a more systematic way by creating a function to go through it:

 walk.through <- function() { tb <- unlist(.Traceback) if(is.null(tb)) stop("no traceback to use for debugging") assign("debug.fun.list", matrix(unlist(strsplit(tb, "\\(")), nrow=2)[1,], envir=.GlobalEnv) lapply(debug.fun.list, function(x) debug(get(x))) print(paste("Now debugging functions:", paste(debug.fun.list, collapse=","))) } unwalk.through <- function() { lapply(debug.fun.list, function(x) undebug(get(as.character(x)))) print(paste("Now undebugging functions:", paste(debug.fun.list, collapse=","))) rm(list="debug.fun.list", envir=.GlobalEnv) } 

Here is a dummy example of its use:

 foo <- function(x) { print(1); bar(2) } bar <- function(x) { x + a.variable.which.does.not.exist } foo(2) # now step through the functions walk.through() foo(2) # undebug those functions again... unwalk.through() foo(2) 

IMO, this doesn't seem like the most sensible thing. It makes sense to simply go to the function where the problem arises (i.e., at the lowest level) and work in the opposite direction.

I have already outlined the logic of this basic procedure in a "favorite debugging trick . "

+5
source share

I like options(error=recover) as detailed earlier on SO . Then they stop at the point of error, and you can check.

+5
source share

(I am the author of the debug package in which mtrace lives)

If the definition of "Subfunction" lives outside of "MyFunction", you can simply mtrace "SubFunction" and do not need mtrace "MyFunction". And functions run faster if they are not "mtrace'd", so itโ€™s good to use mtrace only as you need. (But you probably already know that!)

If "MyFunction" is defined only inside "SubFunction", one trick that might help is to use a conditional breakpoint in "MyFunction". You will need "mtrace (MyFunction)", then run it, and when the debug window appears, find out which line "MyFunction" is defined. Say line 17. Then the following should work:

D (n)> bp (1, F) # no need to show the window again for MyFunction D (n)> bp (18, {mtrace (SubFunction), FALSE}) D (n)> go ()

It should be clear what this does (or it will if you try).

The only disadvantages are: the need to do this again when you change the code "MyFunction" and; the slowdown that can occur with the help of the "MyFunction" itself performed by mtraced.

You can also experiment by adding the argument 'debug.sub' to 'MyFunction', which defaults to FALSE. In the "MyFunction" code, add this line immediately after the definition of "SubFunction":

if (debug.sub) mtrace (SubFunction)

This avoids the need for mtrace 'MyFunction', but requires you to change your code.

+3
source share

All Articles