r - 当外部程序通过 R 的 C API 接口(interface)调用 `Rf_allocXXX` 时,谁在管理内存?

标签 r rcpp

我正在用 Rust 编写一个 R 包,它通过其 C API 接口(interface)与 R 通信。

内存管理对我来说似乎是一个棘手的基本问题。

所以首先让我简要解释一下我的 Rust 程序如何与 R 通信。


首先,在R端,它用.Call()调用一个C动态库.然后将 C 库链接到具有 C 兼容 ABI 的 Rust 静态库。

R 脚本正在执行一些简单的工作,例如输入验证,并根据输入决定调用哪个 C 函数。然后 C 程序将调用传递给底层 Rust 函数,这些函数公开为 C 兼容函数。

到目前为止都非常清楚,一旦 Rust 完成计算并需要将结果发回,它就会变得棘手。


一种选择是直接调用 Rf_allocXXX在 Rust 端运行,并将结果存储在其中。然后将R对象的原始指针传回给C,再传给R。

但我不清楚这是否会导致内存泄漏

在我看来,如果 Rust 调用 Rf_allocXXX ,新的 R objected ( SEXP ) 在 Rust 程序的堆内存上创建。将原始指针传递出去时,Rust 不会销毁对象。但接下来会发生什么?

请注意 SEXP Rust 以这种方式创建的直接传回 C 和 R。没有重新分配。所以我似乎很不清楚这个 SEXP将被 R 的 GC 正确释放。


一个相关的问题,

我从 Rcpp 注意到了什么的源代码是,它似乎只是调用 R 的 C API 来创建其各种向量,这些向量是 SEXP 的包装器。 .

但我还不清楚它是如何处理内存管理的。它只是简单地转动 SEXP返回对象,R 将正确处理 GC?

最佳答案

全部(一如既往)在Writing R Extensions中(而且一如既往地不是最容易找到的……)

简而言之,当您调用 R 扩展包时,您基本上需要调用 R 的 API 及其 Calloc()Free() 例程(和变体) .为什么?因为您返回到 R 的任何都变成了 R 对象,并且与所有其他 R 对象没有区别并且行为相同。包括,非常重要的是,当涉及到垃圾收集时。

唯一的方法是通过 R 自己的分配器。所以 Rcpp 使用它。并创建实际上无法区分的对象。这使得一切正常。

R> Rcpp::cppFunction("IntegerVector foo() { 
+                           IntegerVector v = {1, 2, 3}; return v; }") 
R> foo()
[1] 1 2 3 
R> identical(foo(), c(1L, 2L, 3L))  
[1] TRUE  
R> identical(foo(), 1:3)    
[1] TRUE    
R> 

但作为第一步,您可以在 Rust 中做您的事情来计算结果,然后支付一次性转换成本(从您的对象到 SEXP R 期望的结果一个 .Call()) 。 “先走再跑”等等。 Rust 绑定(bind)会很酷。我想您知道 Jeroen 和其他人已经做了一些工作?

关于r - 当外部程序通过 R 的 C API 接口(interface)调用 `Rf_allocXXX` 时,谁在管理内存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64014024/

相关文章:

r - 提取交互式图中鼠标单击的确切坐标

r - 使用 RestRserve 上传 XLSX 数据

再现 Fisher 线性判别图

r - 从 Rcpp 中获取与基 R 相同的整数样本

RcppArmadillo Gamma 分布在具有相同种子的平台之间不同

r - 矩阵列表乘以标量,Rcpp 中不保留维度属性

c - 为什么相同的函数在链接其他目标文件后表现不同?

r - 是否有一个函数可以将一个大数据帧拆分为 n 个相同大小的较小数据帧(按行),并具有一个较小大小的 n+1 数据帧?

Rcpp 检查列表是否有一个元素

c++ - RcppParallel 中二次型的并行计算