首页 > 解决方案 > 在 R 中执行嵌套 C 代码时发生内存泄漏

问题描述

我目前正在开发一个 R 包,其中时间性能至关重要,这就是我在 C 中实现关键部分的原因。(我习惯于 C。至少现在我不打算使用 C++。)

在我看来,SEXP 结构在让 C 函数内部通信时也非常方便。因此,在我的 C 代码中,所有函数都将 SEXP 作为参数并返回 SEXP。当然,我为每个单独的功能处理了平衡的 PROTECT 和 UNPROTECT。

到目前为止,我的主循环位于 R 中,它一遍又一遍地调用 C 函数。由于这个循环还计算了一些其他的东西,我想把这个循环也转移到 C 中,并编写了一个与 R 循环等效的 C 函数。将这部分转移到 C 现在会导致我以前从未见过的重大内存泄漏:在每次迭代中,使用的内存不断增加,直到分配失败。C 中的循环也可以正确处理 PROTECT。还值得一提的是,在取消执行后调用 gc() 并不能清理数 GB 的 UNPROTECTED SEXP 的混乱。

那么为什么会发生这种内存泄漏呢?R只能在返回R时正确清理吗?在内部处理 SEXP 时是否有 PROTECT/UNPROTECT 的替代方案,例如某种免费的?(我还尝试重写内存密集型部分以使用 R_PreserveObject 和 R_ReleaseObject。)我使用 valgrind 的迭代次数较少,以便程序可以在达到分配限制之前完成。那里没有可见的内存泄漏。

为了说明这个问题,R 中这个相当愚蠢的代码块没有任何泄漏:

while(TRUE) {
  eval <- .Call(my_function, argument1, argument2, 42)
}

现在调用执行此循环的外部 C 函数

.Call(C_loop, argument1, argument2)

SEXP C_loop(SEXP argument1, SEXP argument2) {
  SEXP argument3 = PROTECT(ScalarInteger(42));
  while(1) {
    my_function(argument1, argument2, argument3);
  }
  UNPROTECT(1);
  return R_NilValue;
}

产生泄漏。

标签: rcmemory-leaks

解决方案


推荐阅读