如何在 Windows 中调试(逐行)Rcpp 生成的代码?

2023-11-25

我正在尝试调试Rcpp运行时编译的代码。很长一段时间以来,我一直试图让它发挥作用,但没有成功。 这里提出了一个非常相似的问题:Windows下Rcpp生成的DLL的调试(逐行)它问了同样的问题,但问题和答案都远远超出了我的理解。

这是我所拥有的:

Windows 7 Pro SP1
R 3.5
Rstudio 1.1.463 with Rcpp.
Rbuild Tools from Rstudio. (c++ compiler)

程序: 在 Rstudio 文件 -> 新文件 -> C++ 文件中(使用 timesTwo 函数创建示例文件。)

我在此文件中添加了一个新函数:

// [[Rcpp::export]]
NumericVector timesTwo2(NumericVector x) {
  for(int ii = 0; ii <= x.size(); ii++)
  {
    x.at(ii) = x.at(ii) * 2;
  }
  return x;
}

我在“保存”上检查了“源”并将文件另存为 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()所以结果是一个运行时错误。

问题是如何获得有关此错误的调​​试输出,合理地告诉我发生了什么? 至少我想知道代码中触发异常的行以及使用哪些参数。 此外,我真的很想在异常发生之前逐行执行代码,这样我就可以准确监控正在发生的情况。

我可以安装任何其他程序或应用任何其他设置,只要我能找到有关如何执行此操作的精确详细信息。现在我从头开始只是为了让它发挥作用。谢谢。

Update:我找到了这个网站:使用 gdb 调试 Rcpp C++ 代码我安装了最新的gcc8.1 与gdb

我找到了CXXFLAGS in the makeconf文件位于C:\Program Files\R\R-3.5.1\etc\x64然后我开始了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,但是好像还是无法编译。有人知道错误的原因吗?

我尝试以相同的方式运行 RstudioRgui它开始于许多线程显示在gdb窗口,但 Rstudio 中的所有内容都像以前一样运行,没有来自 Rstudio 或的附加调试信息gdb.

更新2:正如上面的错误指出的那样Rgui没有用于编译的 Rtools,因此我从提供的链接安装了 Rtools。它安装在 C:\Rtools 中,而 Rstudio 安装在 C:\RBuildTools 中。所以我现在有 3 个编译器,Rtools、RbuildTools 和gcc with gdb。 现在可以编译了,但仍然出现与我在 Rstudio 中相同的错误。我希望至少获得更好的错误输出,例如传递的行和值。 指令说Rgui应该有一个断点,但我找不到这样的选项。

Update 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 -d gdb,我也在下面的原始答案中建议,它不适用于 Windows:

--调试器=名称
-d 名称

(仅限 UNIX) 通过调试器名称运行 R。对于大多数调试器(valgrind 和 gdb 的最新版本除外),将忽略更多命令行选项,而应在从调试器内部启动 R 可执行文件时给出。

https://cran.r-project.org/doc/manuals/r-release/R-intro.html#Invoking-R-from-the-command-line

选择:

  1. 在调试器中启动 R:gdb.exe Rgui.exe
  2. 设置断点:break TimesTwo2
  3. Run R: run
  4. 源文件:Rcpp::sourceCpp("debug.cpp")
  5. Use next, print, display单步执行代码。

步骤 1 的替代方法是启动 R,使用以下命令获取 PIDSys.getpid(),附加调试器gdb -p <pid>。你将不得不使用continue代替run.


我现在没有Windows机器,所以以下是在Linux上完成的。不过我希望它是可以转让的。让我们从一个简单的 cpp 文件开始(debug.cpp在我的例子中)包含您的代码:

#include <Rcpp.h>
using Rcpp::NumericVector;

// [[Rcpp::export]]
NumericVector timesTwo2(NumericVector x) {
  for(int ii = 0; ii <= x.size(); ii++)
  {
    x.at(ii) = x.at(ii) * 2;
  }
  return x;
}

/*** R
data = c(1:10)
data
timesTwo2(data)
*/

我可以通过在命令行上调用 R 来重现该错误:

$ R -e "Rcpp::sourceCpp('debug.cpp')"

R version 3.5.1 (2018-07-02) -- "Feather Spray"
[...]

> Rcpp::sourceCpp('debug.cpp')

> 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].
Calls: <Anonymous> ... source -> withVisible -> eval -> eval -> timesTwo2 -> .Call
Execution halted

接下来我们可以启动 Rgdb作为调试器(参见编写 R 扩展正如德克所说):

$ R -d gdb -e "Rcpp::sourceCpp('debug.cpp')"
GNU gdb (Debian 8.2-1) 8.2
[...]
(gdb) break timesTwo2
Function "timesTwo2" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (timesTwo2) pending.
(gdb) run
[...]
> Rcpp::sourceCpp('debug.cpp')
[Thread 0xb40d3b40 (LWP 31793) exited]
[Detaching after fork from child process 31795]

> data = c(1:10)

> data
 [1]  1  2  3  4  5  6  7  8  9 10

> timesTwo2(data)

Thread 1 "R" hit Breakpoint 1, 0xb34f3310 in timesTwo2(Rcpp::Vector<14, Rcpp::PreserveStorage>)@plt ()
   from /tmp/RtmphgrjLg/sourceCpp-i686-pc-linux-gnu-1.0.0/sourcecpp_7c2d7f56744b/sourceCpp_2.so
(gdb)

此时,您可以使用单步执行程序next(要不就n)并使用输出变量print(要不就p)。一个有用的命令也是display:

Thread 1 "R" hit Breakpoint 1, timesTwo2 (x=...) at debug.cpp:5
5   NumericVector timesTwo2(NumericVector x) {
(gdb) n
6     for(int ii = 0; ii <= x.size(); ii++)
(gdb) n
8       x.at(ii) = x.at(ii) * 2;
(gdb) display ii
2: ii = 0
(gdb) n
8       x.at(ii) = x.at(ii) * 2;
2: ii = 0

[...]

2: ii = 9
(gdb) 
46          inline proxy ref(R_xlen_t i) { return start[i] ; }
2: ii = 9
(gdb) 
6     for(int ii = 0; ii <= x.size(); ii++)
2: ii = 10
(gdb) 
8       x.at(ii) = x.at(ii) * 2;
2: ii = 10
(gdb) 
Error in timesTwo2(data) : Index out of bounds: [index=10; extent=10].
Calls: <Anonymous> ... source -> withVisible -> eval -> eval -> timesTwo2 -> .Call
Execution halted
[Detaching after fork from child process 32698]
[Inferior 1 (process 32654) exited with code 01]

顺便说一句,我使用了以下编译标志:

$ R CMD config CXXFLAGS
-g -O2 -Wall -pedantic -fstack-protector-strong -D_FORTIFY_SOURCE=2

您可能想切换到-O0.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 Windows 中调试(逐行)Rcpp 生成的代码? 的相关文章

随机推荐

  • nd_pdo_mysql 和 pdo_mysql 扩展之间有什么区别?

    由于某种原因pdo mysql我们的托管服务器上的 PHP 扩展无法运行使用 MySQL 视图的查询 并出现此错误消息 SQLSTATE HY000 一般错误 1615 准备好的语句需要重新准备 有一个讨论Bug 42041 当 MySQL
  • app.UseErrorHandler() 可以访问错误详细信息吗?

    在我的 MVC4 应用程序中 我覆盖了 global asax csApplication Error object sender EventArgs e 我可以在哪里提取exception statusCode and requested
  • gcloud docker Push 403 禁止

    我正在尝试将 docker 映像推送到 eu gcr io 但收到 403 Forbidden gcloud docker push eu gcr io
  • Schema.org 中网页结构的隐含性

    在阅读了数千篇帖子 问题 博客文章和意见之后 我仍然对如何使用微数据标记网页感到有点困惑 如果微数据的主要目的是帮助搜索引擎更好地理解网页的内容 并且隐式假设网页 那么在 body 元素中从 itemtype Webpage 开始 然后继续
  • 模板类特化的模板方法

    这是我的代码 template
  • 泛型的 JSON 序列化

    我有一堂课 看起来像这样 public class MyData IList
  • Google Chrome 扩展程序的 Paypal 按钮

    我正在尝试向我的 google chrome 扩展添加一个捐赠按钮 因为我喜欢钱 我遇到了麻烦 因为 Chrome 扩展程序尝试在 popup html 窗口中打开 paypal 创建的捐赠按钮 当我单击该按钮时 我的扩展程序会重新启动 并
  • 不带逗号的 NumberFormat 文本字段

    我有一个JFormattedTextField我想接受 5 位数字范围内的数字 以下代码可以正确运行 myNumberBox new JFormattedTextField NumberFormat getIntegerInstance 但
  • Python:以 Value 作为字典获取前 n 个键

    我有一本字典 比如 data sachin score 15000 out 100 Dhoni score 8000 out 80 Shewag score 12000 out 150 我想要两名得分最高的球员 所以我尝试过 key key
  • 将工具提示与 link_to 结合使用 (Ruby on Rails 3.2.3)

    我已经成功使用类似于以下的代码创建了文本工具提示 a href title something text on page a 不过 我想使用 link to 命令为菜单中定义的链接提供工具提示 我已经包含了我希望出现工具提示的声明 li i
  • Perl 脚本可以修改自身吗?

    我想让我的脚本在内部跟踪最后一次修订日期作为评论 这可能吗 在我看来 它需要获取日期 然后打开其脚本文件进行追加 写入数据并保存文件 谢谢 Everone 非常好的答案 根据 GreenMatt 留下的代码片段 我将其放在一起 usr bi
  • 为 UIView 及其所有子视图着色

    有什么方法可以给 UIView 着色吗 不是背景颜色 而是整个 UIView 及其所有子视图 例如 带有星星旋转动画的 UIView 即 UIView 形状不断变化 最终我创建了一个 UIView 类别 可以对 UIView 进行着色 没有
  • Laravel 本地化以及来自 Jetstream / Fortify 的路线

    我有一个新的 Laravel 项目要处理 我们希望以多种语言提供它 我从 JetStream 开始了这个项目 身份验证等路由由 JetStream Fortify 自动处理 然后我添加了https github com mcamara la
  • 如何构建和使用 Google TensorFlow C++ api

    我真的很渴望开始在 C 中使用 Google 新的 Tensorflow 库 网站和文档对于如何构建项目的 C API 确实不清楚 我不知道从哪里开始 有更多经验的人可以通过发现和分享使用 TensorFlow 的 C API 的指南来提供
  • HoughCircles 无法检测到该图像上的圆圈

    我试图检测图像中包含圆点的圆圈 但不幸的是我无法这样做 我正在使用 opencv 霍夫变换 但找不到使其工作的参数 src imread encoded jpg 1 Convert it to gray cvtColor src src g
  • Wget:如果文件已存在,则跳过下载?

    答复如果 wget 中存在文件 则跳过下载 说使用 nc or no clobber but nc不会阻止发送 HTTP 请求以及随后下载文件 如果文件已被完全检索 则下载文件后它不会执行任何操作 如果文件已经存在 是否有办法阻止发出 HT
  • 如何获取 SSAS(或任何其他报告)中两个 TFS 工作项状态之间的时间?

    TFS 的报告中是否有一种方法可以获取工作项在状态之间转换所需的时间 查看中的数据Tfs Warehouse数据库我可以看到有一个工作项的每个修订的记录 并且使用 TSQL 我可以编写一个查询来获取ChangedDate每个状态的变化并区分
  • AngularJS 模块依赖关系 - 澄清?

    我一直在研究 AngularJs 网站上的教程示例 this one The 主要 html 很空 除了ng view and ng app phonecatApp The app js文件包括 var phonecatApp angula
  • GDI+ .NET:宽度超过 202 像素的 LinearGradientBrush 会导致颜色环绕

    如果我用 a 绘制一个宽度超过 202 像素的矩形LinearGradientBrush 我在左侧看到一条彩色条纹 给定一个代码202px宽矩形 private void MainForm Paint object sender Paint
  • 如何在 Windows 中调试(逐行)Rcpp 生成的代码?

    我正在尝试调试Rcpp运行时编译的代码 很长一段时间以来 我一直试图让它发挥作用 但没有成功 这里提出了一个非常相似的问题 Windows下Rcpp生成的DLL的调试 逐行 它问了同样的问题 但问题和答案都远远超出了我的理解 这是我所拥有的