2017-01-12 18 views
0

以下代码编译并正确执行,但每次运行它时,我的R会话完成后都会收到致命错误。我正在运行R版本3.3.2和Rtools 3.3。从Rcpp函数接收结果后会话崩溃

有什么我错过了吗?我如何追踪造成坠机的原因?

#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; 
} 

回答

4

有几个问题与您的代码有问题。我们首先看看如何定义结果矩阵,使用bool,然后详细讨论未定义的行为(UB)作为矩阵子集的结果。


的定义:

NumericMatrix dupMat(300, ncol); 

有两个问题:

  1. 它被放置ncol之前已经被初始化
  2. 假定x矩阵已经nrow固定在300

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

nrow = x.nrow(); 
ncol = x.ncol(); 

Rcpp::NumericMatrix dupMat(nrow, ncol); 

此外,bool值++写入小写。

即,代替TRUEfalse代替FALSE使用true同时设定flag变量的值。


有访问一个NumericMatrix各个元素方式,但是,我们只专注于他们的使用i,j指数。

  • (i,j):以这种方式访问​​单元内放弃一个界限检查和警告后续异常标志如果点不在范围内。实质上,这种访问方法导致UB,因为n = n + 1可以容易地从以外的行索引中去除。当RStudio或R运行后台任务导致崩溃发生时,UB可能会在稍后造成严重后果。
  • .at(i,j):这是首选的方法,因为它提供了边界检查并引发了一个漂亮的例外,例如

错误dupCheckRcpp(A):索引超出范围

其是由下面的代码段触发:

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的主要原因被击中上限是由于放置在每次都重新实例化的第二个for循环内。


不知道你的意图,重复检查的背后,猜测它是检查重复该可能存在矩阵内之外。我会在这里停下来。

+0

很好的答案。它工作完美。 –

+0

未显示代码的目标是检查向量是否在1000 x 245矩阵内复制。这段代码将整个矩阵分解为只有重复的行(〜100-200)以加速检查。 R dupated()函数是将矩阵仅切成复制品的简单方法,但它是超低速。我怀疑可能有内置的C++函数可以更快地使用矢量来完成这个功能,但是我需要一些快速而肮脏的东西,以便我可以立即执行,因此我使用了强力循环。 再次感谢。 –

+0

@SeanS,我可以建议获取rowID,创建一个只包含重复行的矩阵,然后返回列表? – coatless