从 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);

有两个问题:

  1. 放在ncol初始化之前
  2. 假设 x 矩阵 nrow 固定为 300。

dupMat 的实例化移动到 ncolnrow 初始化之后。或者,移动它直到您知道重复行的数量。

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每次。


在不知道重复检查背后的意图的情况下,除了猜测它正在检查 可能 存在于矩阵 中的重复之外.我要到此为止了。