From 太極
Jump to navigation Jump to search


How to debug an R code

How to Easily and Efficiently Conquer Errors in Your Code

debug(), debugonce() and isdebugged() functions

How to quit debugging

press Q and then ENTER

list or undebug all debugged functions

Using assign() in functions

For example, insert the following line to your function

 assign(envir=globalenv(), "GlobalVar", localvar)


  error = rlang::entrace, 
  rlang_backtrace_on_error = "branch")

Debug lapply()/sapply()

Debugging with RStudio

Debug R source code

Build R with debug information

$ ./configure --help
$ ./configure --enable-R-shlib --with-valgrind-instrumentation=2 \
                               --with-system-valgrind-headers \
               CFLAGS='-g -O0 -fPIC' \
               FFLAGS='-g -O0 -fPIC' \
               CXXFLAGS='-g -O0 -fPIC' \
               FCFLAGS='-g -O0 -fPIC' 
$ make -j4
$ sudo make install
# Make sure to create a file <src/Makevars> with something like: CFLAGS=-ggdb -O0
# Or more generally
# CFLAGS=-Wall -Wextra -pedantic -O0 -ggdb
# CXXFLAGS=-Wall -Wextra -pedantic -O0 -ggdb
# FFLAGS=-Wall -Wextra -pedantic -O0 -ggdb

$ tree nidemo
$ R CMD INSTALL nidemo
$ cat bug.R
$ R -f bug.R 
$ R -d gdb
(gdb) r
> library(nidemo)
> Ctrl+C
(gdb) b nid_buggy_freq
(gdb) c  # continue
> buggy_freq("nidemo/DESCRIPTION") # stop at breakpoint 1
(gdb) list
(gdb) n # step through
(gdb) # press RETURN a few times until you see the bug
(gdb) d 1 # delete the first break point
(gdb) b Rf_error # R's C entry point for the error function
(gdb) c
> buggy_freq("nidemo/DESCRIPTION")
(gdb) bt 5 # last 5 stack frames
(gdb) frame 2
(gdb) list
(gdb) p freq_data
(gdb) p ans
(gdb) call Rf_PrintValues(ans)
(gdb) call Rf_PrintValues(fname)
(gdb) q
# Edit buggy.c

$ R CMD INSTALL nidemo # re-install the package
$ R -f bug.R
$ R -d gdb
(gdb) run
> source("bug.R") # error happened
(gdb) bt 5 # show the last 5 frames
(gdb) frame 2
(gdb) list
(gdb) frame 1
(gdb) list
(gdb) p file
(gdb) p fh
(gdb) q
# Edit buggy.c

$ R CMD INSTALL nidemo
$ R -f bug.R


Registering native routines

Pay attention to the prefix argument .fixes (eg .fixes = "C_") in useDynLib() function in the NAMESPACE file.

Example of debugging cor() function

Note that R's cor() function called a C function cor().

 .Call(C_cor, x, y, na.method, method == "kendall")

A step-by-step screenshot of debugging using the GNU debugger gdb can be found on my Github repository