调试加载到R中的共享对象的最有效和最快捷的方法是什么,特别是在OS X Mavericks上?我主要对调试编译的Rcpp代码感兴趣。
我已经阅读了有关使用gdb的调试编译代码(http://cran.r-project.org/doc/manuals/R-exts.html#Debugging-compiled-code)的R外部代码,但是Mavericks并未正式支持gdb。但是,似乎lldb是一个可行的替代方案吗?我找到了最有用的资源,用于研究如何从Dirk对这篇文章的回复中调试R中的编译代码(感谢Dirk!)(Debugging (line by line) of Rcpp-generated DLL under Windows)。
我可以按照下面逐步明确说明的步骤成功调试已编译的Rcpp代码,其他Rcpp新手可能会觉得这很有用(为长度道歉,但我认为最好是明确而不是省略并且是模糊)。但是这个开发过程有点乏味且耗时。
问题:
与我在下面的操作相比,是否有更快速和/或更简单的方法来调试已编译的Rcpp代码?
我是Rstudio的忠实粉丝,并希望合并从该IDE创建的调试共享对象,所以如果有人知道如何做到这一点,我会有兴趣知道吗? Rstudio似乎使用属性,看起来下面的步骤4需要修改,因为编译后在临时目录中似乎没有.cpp文件(在我的示例中,没有“file5156292c0b48.cpp”文件)
步骤:
1)(一次关闭)转到目录〜/ .R(带有。的隐藏目录)。创建一个名为“Makevars”的新文件,并在其中添加行CXXFLAGS=-g -O0 -Wall
。
2)在终端中,键入R -d lldb
以启动R. lldb现在将启动。
3)在lldb命令行输入run
。这将启动R.
4)编译Rcpp代码并找到编译对象的位置。德克对上述帖子的回应显示了一种方法。这是我将在这里使用的一个例子。在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);
')
这会创建一个编译的共享对象和其他文件,可以通过在R中运行setwd(tempdir())和list.files()找到。会有一个.cpp文件,比如“file5156292c0b48.cpp”和.so文件如“file5156292c0b48.so”
5)通过在R命令行运行dyn.load("file5156292c0b48.so")
将共享对象加载到R中
6)现在我们要在这个.so对象中调试C ++代码。点击ctrl + c
返回lldb。现在我想在file5156292c0b48.cpp文件中的特定行设置一个断点。我通过打开另一个终端并查看file5156292c0b48.cpp中感兴趣的行号来找到正确的行号。假设它是第31行,它对应于theAnswer = 1中的行;以上在我的例子中。然后我在lldb命令行输入:breakpoint set -f file5156292c0b48.cpp -l 31
。调试器打印出已经设置了断点和其他一些东西...
7)通过在lldb中运行cont
返回R(在我按下Enter键之前,R提示不会自动出现)并调用该函数。在R命令行运行fun()
。现在我正在调试共享对象(点击n转到下一行,p [对象名]打印变量等)....
答案 0 :(得分:10)
要调试这样的简单Rcpp脚本,你可以做的一件事就是创建一个嵌入了R的.cpp
应用程序(带有一个main)。这样你可以直接使用Xcode调试它,这将为你提供一个很好的调试经验。
当您开始想要调试包时,它会变得更加复杂。
答案 1 :(得分:2)
这很难。我尝试使用独立的C ++应用程序来运行Xcode和Eclipse,但是很难让所有的头文件和库工作。此外,RcppExport代码通过一个似乎真正混淆Xcode的指针调用你的真实R函数,我无法进入我的函数。
我最终得到了(gdb或lldb):
在R:
R -d lldb
在调试器中,设置断点:
b functionName
run
在R:
.Call(etc) # or just call your R code which invokes compiled C/C++ code
然后在调试器中一旦发生中断,你就可以步进,检查帧等等。
这个lldb / gdb command quick reference帮了很多忙。
忘记在此时尝试在GUI中执行此操作。希望Rstudio能够实现这一目标。