3

由于我不明白的原因,我的 Rcpp 代码偶尔会失败(SEGFAULT 等)。该代码创建了一个大型 data.frame,然后尝试通过调用 R 子集函数[.data.frame) 从创建该框架的同一方法中获取此 data.frame 的一个子集。它的一个非常简化的版本如下所示:

library(Rcpp)
src <- '// R function to subset data.frame - what will be called to subset
DataFrame test() {
Function subsetinR("[.data.frame"); 

// Make a dataframe in Rcpp to subset
size_t n = 100;
auto df =  DataFrame::create(Named("a") = std::vector<double> (n, 2.0),
                             Named("b") = std::vector<double> (n, 4.0));

// Now make a vector to subset with 
LogicalVector filter = LogicalVector::create(n, TRUE);
for (size_t i =0; i < n; i++) {
    if (i % 2 == 0) filter[i] = FALSE;
}   

// Subset, here is where it fails!
df = subsetinR(df, filter, R_MissingArg);
return df; 
}'  

fun <- cppFunction(plugins=c("cpp11"), src, verbose = TRUE, depends="Rcpp") 
fun()

但是,虽然这偶尔会起作用,但有时它会失败并出现以下错误:

*** caught segfault ***
   address 0x7ff700000030, cause 'memory not mapped'`

有谁知道出了什么问题?

注意:这不是重复的. 我已经看到其他堆栈溢出答案,它们通过利用每个向量上的子集来创建向量,例如

  // Next up, create a new DataFrame Object with selected rows subset. 
  return Rcpp::DataFrame::create(Rcpp::Named("val1")  = val1[idx],
                                 Rcpp::Named("val2")  = val2[idx],
                                 Rcpp::Named("val3")  = val3[idx],
                                 Rcpp::Named("val3")  = val4[idx]
                                 );

但是,我明确希望避免重复[idx]子集,因为在构建 data.frame 时不知道 idx(它只在最后才知道),我希望找到一种不涉及重复调用的方法那。如果可以在最后一次转换 data.frame,那会很好。

4

1 回答 1

2

这里的问题是它LogicalVector::create()没有做你期望的事情——它返回一个长度为 2 的向量,其中包含元素TRUETRUE。换句话说,您的代码:

LogicalVector 过滤器 = LogicalVector::create(n, TRUE);

生成的不是一个长度n为 valuesTRUE的逻辑向量,而是一个长度为 2 的逻辑向量,第一个元素是 'truthy' 等等TRUE,第二个是明确的TRUE

您可能打算只使用常规构造函数,例如LogicalVector(n, TRUE).

于 2016-07-22T06:21:18.883 回答