2017-01-12 21 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