使用消毒剂(来自rhub)运行时,Rcpp功能出现segfault

时间:2018-07-16 22:23:40

标签: rcpp r-package

我正在使用Rcpp Function编写一个程序包,该程序包可以编译,并且R CMD Check也可以正常工作。之前,包的cvode函数的输入是XPtr,但是现在输入既可以是XPtr也可以是RRcpp函数(实现是基于earlier post)。当前,RRcppRcpp::XPtr中的输入函数在程序包中起作用。

该软件包以前曾经有clang-UBSAN issues,所以我现在尝试使用rhub软件包预先检测到它们。从check_with_sanitizers()包运行rhub命令时,出现以下错误:

eval.c:677:21: runtime error: member access within null pointer of type 'struct SEXPREC'

─   *** caught segfault ***
   address (nil), cause 'memory not mapped'
   Segmentation fault (core dumped)

在下面的代码中,我已经能够将错误隔离到行ydot1 = rhs_fun(t, y1);上,即,注释/取消注释上面的表达式会重现该错误。

我的问题是-在调用rhs_fun Function之前我应该​​进行一次检查,以避免segmentation fault错误吗?

注意-check_with_valgrind()不会产生错误。

谢谢!

// struct to use if R or Rcpp function is input as RHS function
struct rhs_func{
  Function rhs_eqn;
};

int rhs_func(realtype t, N_Vector y, N_Vector ydot, void* user_data){

  // convert y to NumericVector y1
  int y_len = NV_LENGTH_S(y);

  NumericVector y1(y_len);    // filled with zeros
  realtype *y_ptr = N_VGetArrayPointer(y);
  for (int i = 0; i < y_len; i++){
    y1[i] = y_ptr[i];
  }

  // convert ydot to NumericVector ydot1
  // int ydot_len = NV_LENGTH_S(ydot);

  NumericVector ydot1(y_len);    // filled with zeros

  // // cast void pointer to pointer to struct and assign rhs to a Function
  struct rhs_func *my_rhs_fun = (struct rhs_func*)user_data;

  if(my_rhs_fun){

    Function rhs_fun = (*my_rhs_fun).rhs_eqn;

    // use the function to calculate value of RHS ----
    // Uncommenting the line below gives runtime error
    // ydot1 = rhs_fun(t, y1);

  }
  else {

    stop("Something went wrong, stopping!");
  }


  // convert NumericVector ydot1 to N_Vector ydot
  realtype *ydot_ptr = N_VGetArrayPointer(ydot);
  for (int i = 0; i<  y_len; i++){
    ydot_ptr[i] = ydot1[i];
  }

  // everything went smoothly
  return(0);
}

一个更新-根据以下评论,我添加了检查。因此检查成功,但是随着代码转到rhs_fun消息,我可以看到stop为NULL。

 if(my_rhs_fun){
    Function rhs_fun = (*my_rhs_fun).rhs_eqn;
    // use the function to calculate value of RHS ----
    if (rhs_fun){
      ydot1 = rhs_fun(t, y1);
    }
    else{
      stop("Something went wrong");
    }
  }
  else {
    stop("Something went wrong, stopping!");
  }

添加的检查也添加到结构中

  if (Rf_isNull(input_function)){

    stop("Something is wrong with input function, stopping!");
  }

检查成功,但是在打印rhs_fun消息时,我看到NULLelse

   Error in cvode(time_vec, IC, ODE_R, reltol, abstol) : 
     Something went wrong
   Execution halted

不确定为什么,因为我尝试的示例在没有抱怨的情况下仍然有效。

1 个答案:

答案 0 :(得分:2)

=引用最有可能的候选人是NULL。因此,在执行功能之前进行测试很有意义:

rhs_fun

R API函数if(rhs_fun) { ... } else { stop(...) } 在这里不合适,因为它会检查类型为Rf_isNull的{​​{1}}并为实际的SEXP进行段错误。

此外,我将检查您是否没有在结构中插入NULL引用,尽管我发现那里不太可能出现任何问题。

总体而言,这只是一种解决方法。知道是什么触发了这种行为会很有趣。