从 Rcpp 函数接收结果后会话崩溃
Session crash after receiving results from Rcpp function
以下代码可以正确编译和执行,但每次我 运行 它时,我的 R 会话在完成后不久就会出现致命错误。我正在 运行ning R 版本 3.3.2 和 Rtools 3.3。
有什么我遗漏的吗?我如何追踪导致崩溃的原因?
#include<Rcpp.h>
using namespace Rcpp;
NumericMatrix dupCheckRcpp(NumericMatrix x) {
int nrow, ncol;
int i, j, k, m, n;
bool flag;
NumericMatrix dupMat(300,ncol);
n = 0;
nrow = 0; ncol = 0;
nrow = x.nrow();
ncol = x.ncol();
for (i = 0; i < nrow - 1 ; ++i) {
for (j = i + 1; j < nrow; ++j) {
flag = TRUE;
for (k = 0; k < ncol; ++k) {
if (x(i,k) != x(j,k)) {
flag = FALSE;
break;
}
}
if (flag == TRUE) {
for (m = 0; m < ncol; ++m) {
dupMat(n,m) = x(i,m);
}
n = n + 1;
}
}
}
return dupMat;
}
您的代码存在一些问题。我们首先查看结果矩阵的定义方式、bool
的使用,然后详细说明 未定义行为 (UB) 作为矩阵子集的结果。
定义:
NumericMatrix dupMat(300, ncol);
有两个问题:
- 放在
ncol
初始化之前
- 假设
x
矩阵 nrow
固定为 300。
将 dupMat
的实例化移动到 ncol
和 nrow
初始化之后。或者,移动它直到您知道重复行的数量。
nrow = x.nrow();
ncol = x.ncol();
Rcpp::NumericMatrix dupMat(nrow, ncol);
此外,bool
C++ 中的值以小写形式书写。
即在设置flag
变量的值时,用true
代替TRUE
,用false
代替FALSE
。
有 三种 种方法来访问 NumericMatrix
中的单个元素,但是,我们只关注 两种其中使用 i,j
个索引。
(i,j)
:以这种方式访问元素会放弃 边界检查 和随后的异常标志,如果该点不在 运行ge 内则发出警告。本质上,这种访问方法导致了 UB,因为 n = n + 1
可以很容易地 超出 行索引。当 RStudio 或 R 运行 后台任务导致崩溃发生时,UB 可能在稍后造成严重破坏。
.at(i,j)
:这是首选方法,因为它提供边界检查并抛出一个漂亮的异常,例如
Error in dupCheckRcpp(a) : index out of bounds
由以下代码片段触发:
if (flag == true) {
for (m = 0; m < ncol; ++m) {
Rcpp::Rcout << "dupMat (" << n << ","<< m << ")" << std::endl <<
"x (" << i << ","<< m << ")" << std::endl;
dupMat.at(n, m) = x.at(i, m);
}
n = n + 1; // able to exceed nrow.
}
n = n + 1
达到上限的主要原因是由于放置在 second for
循环内,得到 re-instantiated每次。
在不知道重复检查背后的意图的情况下,除了猜测它正在检查 可能 存在于矩阵 行 中的重复之外.我要到此为止了。
以下代码可以正确编译和执行,但每次我 运行 它时,我的 R 会话在完成后不久就会出现致命错误。我正在 运行ning R 版本 3.3.2 和 Rtools 3.3。
有什么我遗漏的吗?我如何追踪导致崩溃的原因?
#include<Rcpp.h>
using namespace Rcpp;
NumericMatrix dupCheckRcpp(NumericMatrix x) {
int nrow, ncol;
int i, j, k, m, n;
bool flag;
NumericMatrix dupMat(300,ncol);
n = 0;
nrow = 0; ncol = 0;
nrow = x.nrow();
ncol = x.ncol();
for (i = 0; i < nrow - 1 ; ++i) {
for (j = i + 1; j < nrow; ++j) {
flag = TRUE;
for (k = 0; k < ncol; ++k) {
if (x(i,k) != x(j,k)) {
flag = FALSE;
break;
}
}
if (flag == TRUE) {
for (m = 0; m < ncol; ++m) {
dupMat(n,m) = x(i,m);
}
n = n + 1;
}
}
}
return dupMat;
}
您的代码存在一些问题。我们首先查看结果矩阵的定义方式、bool
的使用,然后详细说明 未定义行为 (UB) 作为矩阵子集的结果。
定义:
NumericMatrix dupMat(300, ncol);
有两个问题:
- 放在
ncol
初始化之前 - 假设
x
矩阵nrow
固定为 300。
将 dupMat
的实例化移动到 ncol
和 nrow
初始化之后。或者,移动它直到您知道重复行的数量。
nrow = x.nrow();
ncol = x.ncol();
Rcpp::NumericMatrix dupMat(nrow, ncol);
此外,bool
C++ 中的值以小写形式书写。
即在设置flag
变量的值时,用true
代替TRUE
,用false
代替FALSE
。
有 三种 种方法来访问 NumericMatrix
中的单个元素,但是,我们只关注 两种其中使用 i,j
个索引。
(i,j)
:以这种方式访问元素会放弃 边界检查 和随后的异常标志,如果该点不在 运行ge 内则发出警告。本质上,这种访问方法导致了 UB,因为n = n + 1
可以很容易地 超出 行索引。当 RStudio 或 R 运行 后台任务导致崩溃发生时,UB 可能在稍后造成严重破坏。.at(i,j)
:这是首选方法,因为它提供边界检查并抛出一个漂亮的异常,例如
Error in dupCheckRcpp(a) : index out of bounds
由以下代码片段触发:
if (flag == true) {
for (m = 0; m < ncol; ++m) {
Rcpp::Rcout << "dupMat (" << n << ","<< m << ")" << std::endl <<
"x (" << i << ","<< m << ")" << std::endl;
dupMat.at(n, m) = x.at(i, m);
}
n = n + 1; // able to exceed nrow.
}
n = n + 1
达到上限的主要原因是由于放置在 second for
循环内,得到 re-instantiated每次。
在不知道重复检查背后的意图的情况下,除了猜测它正在检查 可能 存在于矩阵 行 中的重复之外.我要到此为止了。