1

I am writing some code, and when running, it aborted. The r version is 3.5.1. I think there is something wrong with my rcpp code, but I can't find it. It just shows R session aborted.

################I don't think there is anything wrong in this part.
#include <Rcpp.h>

Rcpp::LogicalVector logical_index(Rcpp::IntegerVector idx, R_xlen_t n) {
  bool invert = false; 
  Rcpp::LogicalVector result(n, false);

  for (R_xlen_t i = 0; i < idx.size(); i++) {
    if (!invert && idx[i] < 0) invert = true;
    result[std::abs(idx[i])] = true;
  }

  if (!invert) return result;
  return !result;
}


// [[Rcpp::export]]
Rcpp::NumericVector 
  Subset(Rcpp::NumericVector x, Rcpp::IntegerVector idx) {
    return x[logical_index(idx, x.size())];
  }
# ################There maybe something wrong in this part.
library(Rcpp)
library(gRbase)
vec=0:13
a=combnPrim(vec,4)
cppFunction("
NumericVector r_test(NumericMatrix a, Function comp, Function fct,Function 
tempf, Function combnPrim, NumericVector Fv, NumericVector vec, Function 
Subset){
        NumericVector if1(4);
        NumericVector if2(2);
        NumericVector if3(4);
        NumericVector if4(4);
        NumericVector seq(14);
        NumericMatrix b(2,45);
        NumericMatrix c(4,70);
        for (int i1=0; i1<=a.ncol()-1; i1++){
        if1=a (_, i1);
        b=combnPrim(Subset(vec,-(if1)),2);
        for (int i2=0; i2<=b.ncol()-1; i2++){
        if2=b (_, i2);
        c=combnPrim(Subset(Subset(vec,-(if1)),-(if2)),4);
        for (int i3=0; i3<=c.ncol()-1; i3++){
        if3=c (_, i3);
        if4=Subset(Subset(Subset(vec,-(if1)),-(if2)),-(if3));
        seq=tempf(if1,if2,if3,if4);
        }}}return if1;}")

Fv=7.001327
setwd("D:/STAT 602")

sourceCpp("Subset.cpp")

fct=function(seq,data,fact){
  return(anova(lm(data[seq]~as.factor(fact)))$`F value`[1])
}
tempf=function(x1,x2,x3,x4){
  return(c(x1,x2,x3,x4))
}
comp=function(x,y){
  return(x>y)
}
r_test(a,comp, fct, tempf, combnPrim, Fv, vec, Subset)
#

combnPrim is used to find all combination of a vector, and it outputs a matrix, and Subset is the same use as vector[-i]. Individually, all function can act well in cppFunction, but when putting them like this, things go wrong.

S.Shen
  • 23
  • 3
  • 1
    Could you try to downsize your example to a minimal reproducible example please ? – F. Privé Feb 09 '19 at 19:07
  • @F.Privé well, when vec contains 6 or less elements, it is okay, but the real situation is that I need 24 elements. I hope there is a way to deal with this large amount of elements. – S.Shen Feb 09 '19 at 19:11
  • Two ideas: 1) Run R from the command line. Often it will produce an error before exiting. 2) replace vector access via `[]` with `()`. The latter does bounds checking. – Ralf Stubner Feb 10 '19 at 06:58
  • @RalfStubner I don’t quite understand what (1) means, since my r_test is a whole function, do you mean separate this apart and try to see which line cause error? In that case, actually every line works well separately. For (2), actually there isn’t any [] in my code...... – S.Shen Feb 10 '19 at 14:05
  • No, I did not mean running the lines separately. I meant not using a GUI like RStudio, which unfortunately hides such error messages. I don't know if `RGui.exe` behaves more reasonable. For (2), you first code block contains several places of the form `vector[index]`. – Ralf Stubner Feb 10 '19 at 14:38
  • @RalfStubner For (1) I tried rgui and it closed automatically. For (2) it seems that we can’t use () in cpp, since it shows error. – S.Shen Feb 10 '19 at 14:59

1 Answers1

2

Since this code is pretty convoluted, I'm not going to hunt for the exact, specific bug. However, I can confirm that @RalfStubner was right that your problem is that you're trying to access an element of a vector that does not exist.

If you change logical_index() to

LogicalVector logical_index(IntegerVector idx, R_xlen_t n) {
    bool invert = false;
    LogicalVector result(n, false);

    for (R_xlen_t i = 0; i < idx.size(); i++) {
        if (!invert && idx(i) < 0) invert = true;
        result(std::abs(idx(i))) = true;
    }

    if (!invert) return result;
    return !result;
}

so that element access is done via () rather than [] to ensure bounds checking,1 rather than just aborting, I see the following:

r_test(a,comp, fct, tempf, combnPrim, Fv, vec, Subset)

Error in r_test(a, comp, fct, tempf, combnPrim, Fv, vec, Subset) :
Evaluation error: Index out of bounds: [index=10; extent=8]..

This means you're trying to access an element of a vector that does not exist. I can also tell you the basic reason why this is happening: In logical_vector(), when an element of idx is greater than n, this will occur. So, at some point in r_test(), you are calling Subset() with idx that has an element greater than x.size().


1 You are right that you'll get an error trying to use () for vector subsetting when subsetting a vector by another vector. However, this works when accessing one element of a vector.

duckmayr
  • 16,303
  • 3
  • 35
  • 53
  • That helped! Actually that subset function is copied from the internet, and I only checked if it works, but didn’t expect that it will have other errors. Thanks! – S.Shen Feb 11 '19 at 02:45
  • Good catch concerning subsetting by vector vs. subsetting by single value! – Ralf Stubner Feb 11 '19 at 09:24