What is the most productive and quickest way to debug shared objects that are loaded into R, in particular on OS X Mavericks? I'm primarily interested in debugging compiled Rcpp code.
I have read the R externals on debugging compiled code (http://cran.r-project.org/doc/manuals/R-exts.html#Debugging-compiled-code) which favours using gdb, but gdb isn't officially supported on Mavericks. However, it seems that lldb is a viable alternative? I found the most useful resource for working out how to debug compiled code in R from Dirk's response to this post (Thanks Dirk!) (Debugging (line by line) of Rcpp-generated DLL under Windows).
I can successfully debug compiled Rcpp code by following the steps which I outline below explicitly step by step, which other Rcpp novices may find this useful (apologies for the length, but I figure it's better to be clear than to omit and be vague). But this development process is a bit tedious and time consuming.
Questions:
is there a faster and/or easier way to debug compiled Rcpp code, compared to what I do below?
I'm a big fan of Rstudio, and would love to incorporate debugging shared objects created from that IDE, so if anyone knows how to do this, I would be interested to know? Rstudio seems to use attributes, and it appears that step 4 below needs modification, because there doesn't seem to be a .cpp file in the temporary directory after compiling (in my example below, there is no "file5156292c0b48.cpp" file)
The steps:
1) (One off) Go to the directory ~/.R (a hidden directory with the .). Create a new file called "Makevars" and in it add the line CXXFLAGS=-g -O0 -Wall
.
2) In the terminal, type R -d lldb
to launch R. lldb will now start.
3) Type run
at the lldb command line. This will start R.
4) Compile the Rcpp code and find the location of the compiled objects. Dirk's response to the above mentioned post shows one way to do this. Here is an example I'll use here. Run the following commands in R:
library(inline)
fun <- cxxfunction(signature(), plugin="Rcpp", verbose=TRUE, body='
int theAnswer = 1;
int theAnswer2 = 2;
int theAnswer3 = 3;
double theAnswer4 = 4.5;
return wrap(theAnswer4);
')
This creates a compiled shared object and other files which can be found by running setwd(tempdir()) and list.files() in R. There will be a .cpp file, like "file5156292c0b48.cpp" and .so file like "file5156292c0b48.so"
5) Load the shared object into R by running dyn.load("file5156292c0b48.so")
at the R command line
6) Now we want to debug the C++ code in this .so object. Go back to lldb by hitting ctrl + c
. Now I want to set a break point at a specific line in the file5156292c0b48.cpp file. I find the correct line number by opening another terminal and looking at the line number of interest in file5156292c0b48.cpp. Say it's line 31, which corresponds to the line int theAnswer = 1; above in my example. I then type at the lldb command line: breakpoint set -f file5156292c0b48.cpp -l 31
. The debugger prints back that a break point has been set and some other stuff...
7) Go back to R by running cont
in lldb (the R prompt doesn't automatically appear for me until I hit enter) and call the function. Run fun()
at the R command line. Now I am debugging the shared object (hit n to go to next line, p [object name] to print variables etc)....
To debug simple Rcpp scripts like this, one thing you can do is create a .cpp
application (with a main) that embeds R. This way you can debug it directly with Xcode which will give you a good debugging experience.
It gets more complicate when you start to want to debug packages.
This is tough. I tried Xcode and Eclipse with a standalone C++ application, but it was so difficult to get all the headers and libraries working. Furthermore, the RcppExport code calls your real R function through a pointer which seemed to really confuse Xcode, and I couldn't step into my function.
I ended up with (gdb or lldb):
In R:
R -d lldb
In debugger, set breakpoint:
b functionName
run
In R:
.Call(etc) # or just call your R code which invokes compiled C/C++ code
Then back in debugger once break happens, you can step, examine frames, etc.
This lldb/gdb command quick reference helped a lot.
Forget about trying to do this in a GUI at this point. Hopefully Rstudio will get this going.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With