运行 消毒剂时 Rcpp 函数的段错误(来自 rhub)
segfault on Rcpp function when running with sanitizers (from rhub)
我正在使用 Rcpp
Function
编写一个包,包可以编译,并且 R CMD Check
也可以正常工作。早些时候,包的 cvode
函数的输入是 XPtr
,但现在输入可以是 XPtr
或 R
或 Rcpp
函数(实现是基于 )。目前,R
、Rcpp
和 Rcpp::XPtr
中的输入函数在包中工作。
该软件包以前有 clang-UBSAN issues,所以我现在尝试使用 rhub
软件包预先检测它们。在 rhub
包的 运行 check_with_sanitizers()
命令上,我收到以下错误:
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);
行,即 commenting/un-commenting 上面的表达式重现了错误。
我的问题是 - 在调用 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
是 NULL,因为代码转到 stop
消息。
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
不知道为什么,因为我试过的例子没有投诉。
最有可能成为 NULL
参考的候选人是 rhs_fun
。因此在执行函数之前进行测试是有意义的:
if(rhs_fun) {
...
} else {
stop(...)
}
R API 函数 Rf_isNull
在这里不合适,因为它检查类型 NILSXP
的 SEXP
和实际 [=16= 的段错误].
此外,我会检查您是否没有在结构中插入 NULL 引用,但我发现那里不太可能出现任何问题。
总的来说,这只是一种解决方法。知道是什么触发了这种行为会很有趣。
我正在使用 Rcpp
Function
编写一个包,包可以编译,并且 R CMD Check
也可以正常工作。早些时候,包的 cvode
函数的输入是 XPtr
,但现在输入可以是 XPtr
或 R
或 Rcpp
函数(实现是基于 R
、Rcpp
和 Rcpp::XPtr
中的输入函数在包中工作。
该软件包以前有 clang-UBSAN issues,所以我现在尝试使用 rhub
软件包预先检测它们。在 rhub
包的 运行 check_with_sanitizers()
命令上,我收到以下错误:
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);
行,即 commenting/un-commenting 上面的表达式重现了错误。
我的问题是 - 在调用 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
是 NULL,因为代码转到 stop
消息。
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
不知道为什么,因为我试过的例子没有投诉。
最有可能成为 NULL
参考的候选人是 rhs_fun
。因此在执行函数之前进行测试是有意义的:
if(rhs_fun) {
...
} else {
stop(...)
}
R API 函数 Rf_isNull
在这里不合适,因为它检查类型 NILSXP
的 SEXP
和实际 [=16= 的段错误].
此外,我会检查您是否没有在结构中插入 NULL 引用,但我发现那里不太可能出现任何问题。
总的来说,这只是一种解决方法。知道是什么触发了这种行为会很有趣。