我正在使用Rcpp
Function
编写一个程序包,该程序包可以编译,并且R CMD Check
也可以正常工作。之前,包的cvode
函数的输入是XPtr
,但是现在输入既可以是XPtr
也可以是R
或Rcpp
函数(实现是基于earlier post)。当前,R
,Rcpp
和Rcpp::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
消息时,我看到NULL
是else
Error in cvode(time_vec, IC, ODE_R, reltol, abstol) :
Something went wrong
Execution halted
不确定为什么,因为我尝试的示例在没有抱怨的情况下仍然有效。
答案 0 :(得分:2)
=
引用最有可能的候选人是NULL
。因此,在执行功能之前进行测试很有意义:
rhs_fun
R API函数if(rhs_fun) {
...
} else {
stop(...)
}
在这里不合适,因为它会检查类型为Rf_isNull
的{{1}}并为实际的SEXP
进行段错误。
此外,我将检查您是否没有在结构中插入NULL引用,尽管我发现那里不太可能出现任何问题。
总体而言,这只是一种解决方法。知道是什么触发了这种行为会很有趣。