【发布时间】:2018-12-04 22:23:03
【问题描述】:
我正在尝试在运行时调试Rcpp 编译的代码。很长一段时间以来,我一直试图让这个工作不成功。
这里提出了一个非常相似的问题:Debugging (line by line) of Rcpp-generated DLL under Windows 提出了同样的问题,但问题和答案都远远超出了我的理解。
这是我所拥有的:
Windows 7 Pro SP1
R 3.5
Rstudio 1.1.463 with Rcpp.
Rbuild Tools from Rstudio. (c++ compiler)
程序: 在 Rstudio File->New File->C++ File 中(创建一个带有 timesTwo 函数的示例文件。)
我在这个文件中添加了一个新函数:
// [[Rcpp::export]]
NumericVector timesTwo2(NumericVector x) {
for(int ii = 0; ii <= x.size(); ii++)
{
x.at(ii) = x.at(ii) * 2;
}
return x;
}
我在 Save 上检查了 Source 并将文件保存为 RcppTest.cpp,它成功地获取或编译了文件。
在 Rstudio 中运行代码:
data = c(1:10)
data
[1] 1 2 3 4 5 6 7 8 9 10
timesTwo2(data)
Error in timesTwo2(data) : Index out of bounds: [index=10; extent=10].
错误是因为在for循环中是<= x.size()所以结果是运行时错误。
问题是如何获得有关此错误的调试输出,合理地告诉我发生了什么? 至少我想知道代码中触发异常的行以及使用哪些参数。 此外,我真的很想在异常之前逐行执行代码,这样我就可以准确地监控正在发生的事情。
我可以安装任何其他程序或应用任何其他设置,只要我能找到有关如何执行此操作的详细信息。现在我从头开始只是为了让它工作。谢谢。
更新:
我找到了这个网站:Debugging Rcpp c++ code using gdb
我用gdb安装了最新的gcc 8.1
我在位于C:\Program Files\R\R-3.5.1\etc\x64 的makeconf 文件中找到了CXXFLAGS
然后我按照建议启动了Rgui,但是当我尝试Rcpp:::sourceCpp 时出现错误:
> library(Rcpp)
> Rcpp::sourceCpp('Rcpptest.cpp')
C:/PROGRA~1/R/R-35~1.1/etc/x64/Makeconf:230: warning: overriding recipe for target '.m.o'
C:/PROGRA~1/R/R-35~1.1/etc/x64/Makeconf:223: warning: ignoring old recipe for target '.m.o'
c:/Rtools/mingw_64/bin/g++ -I"C:/PROGRA~1/R/R-35~1.1/include" -DNDEBUG -I"C:/Users/Michael/Documents/R/win-library/3.5/Rcpp/include" -I"C:/PROGRA~1/R/R-35~1.1/bin/x64" -ggdb -O0 -Wall -gdwarf-2 -mtune=generic -c Rcpptest.cpp -o Rcpptest.o
process_begin: CreateProcess(NULL, c:/Rtools/mingw_64/bin/g++ -IC:/PROGRA~1/R/R-35~1.1/include -DNDEBUG -IC:/Users/Michael/Documents/R/win-library/3.5/Rcpp/include -IC:/PROGRA~1/R/R-35~1.1/bin/x64 -ggdb -O0 -Wall -gdwarf-2 -mtune=generic -c Rcpptest.cpp -o Rcpptest.o, ...) failed.
make (e=2): The system cannot find the file specified.
make: *** [C:/PROGRA~1/R/R-35~1.1/etc/x64/Makeconf:215: Rcpptest.o] Error 2
Error in Rcpp::sourceCpp("Rcpptest.cpp") :
Error 1 occurred building shared library.
WARNING: The tools required to build C++ code for R were not found.
Please download and install the appropriate version of Rtools:
http://cran.r-project.org/bin/windows/Rtools/
看起来它正在加载新的CXXFLAGS,它正在使用DEBUG,但它似乎仍然无法编译。有人知道这个错误的原因吗?
我尝试以与 Rgui 相同的方式运行 Rstudio,它开始时在 gdb 窗口中显示了许多线程,但 Rstudio 中的所有内容都像以前一样运行,没有来自 Rstudio 或 gdb 的额外调试信息。
更新 2:
由于上述错误表明Rgui 没有用于编译的 Rtools,因此我从提供链接安装了 Rtools。它安装在 C:\Rtools 中,而 Rstudio 安装在 C:\RBuildTools 中。所以我现在有 3 个编译器,Rtools、RbuildTools 和 gcc 和 gdb。
它现在可以编译,但仍然给出与我在 Rstudio 中相同的错误。我想至少得到更好的错误输出,比如传递的行和值。
指令说Rgui 应该有一个断点点,但我找不到这样的选项。
更新 3
我终于能够设置并运行 Linux 安装(Ubuntu 16.04.05)。
首先是我的CXXFLAGS:
$ R CMD config CXXFLAGS
-g -O0 -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g
我必须在我的主目录中创建一个 .R 文件夹,并在其中创建一个 Makevar 文件,其中只有一行
CXXFLAGS = -g -O0 -Wall -pedantic -fstack-protector-strong -D_FORTIFY_SOURCE=2
仅此一项就花了好几个小时,因为它实际上并没有说要制作文件夹和文件。
然后我在断点处执行 Ralf 发布的命令:
> timesTwo2(d1)
Thread 1 "R" hit Breakpoint 1, timesTwo2 (x=...) at RcppTest.cpp:19
19 NumericVector timesTwo2(NumericVector x) {
(gdb) n
20 for (int ii = 0; ii <= x.size(); ii++)
(gdb) n
22 x.at(ii) = x.at(ii) * 2;
(gdb) display ii
1: ii = 0
(gdb) n
20 for (int ii = 0; ii <= x.size(); ii++)
1: ii = 0
(gdb) n
22 x.at(ii) = x.at(ii) * 2;
1: ii = 1
(gdb) n
20 for (int ii = 0; ii <= x.size(); ii++)
1: ii = 1
(gdb) display x.at(ii)
2: x.at(ii) = <error: Attempt to take address of value not located in memory.>
(gdb) n
22 x.at(ii) = x.at(ii) * 2;
1: ii = 2
2: x.at(ii) = <error: Attempt to take address of value not located in memory.>
(gdb)
最后在n = 10:
1: ii = 10
2: x.at(ii) = <error: Attempt to take address of value not located in memory.>
(gdb) n
0x00007ffff792d762 in Rf_applyClosure () from /usr/lib/R/lib/libR.so
(gdb)
这绝对是我调试的最远的一次,但这是一个非常基本的功能,调试输出甚至错误输出都不是很有用。它给了我它正在执行的行,它可以显示 ii,但我无法显示数组值或整个数组。是否可以创建一个更具体的断点,使其仅在ii == 10 时中断?
理想情况下,我希望在 Rstudio 或其他可以显示整个矢量的 GUI 中使用它。还在做更多的测试。
【问题讨论】:
-
请参阅编写 R 扩展了解调用调试器。远非理想,但我们有,除了旧的
print声明。 -
我的 cpp 文件在我开发它们时到处都是
Rcpp::Rcout << thistestobj << std::endl;语句。 -
有时,当我遇到
Rcpp的问题时,我会尝试将所有内容都转换为纯c++(例如NumericVector -->> std::vector<double>)并使用Visual Studio 中的调试器。工作量很大,但有时,仅使用print语句就很难找到难以捉摸的错误。 -
Rcpp::Rcput
-
Joseph,转换为 c++ 和 Visual Studio 会有什么帮助?不久前,我能够设置 Eclipse,以便我可以在 Eclipse 中编写代码,但我仍然无法在其中调试,它最终变得不稳定,所以回到 Rstudio。如果在我的小例子中我使用向量而不是数字向量,我将如何继续?谢谢。