Я пытаюсь использовать внешние указатели в пакете, но я столкнулся с проблемой, когда казалось, что финализатор не вызывается, и память просочилась.
Ниже приведен чрезвычайно надуманный пример проблемы:
#include <Rcpp.h>
using namespace Rcpp;
void finalize(SEXP xp){
delete static_cast< std::vector<double> *>(R_ExternalPtrAddr(xp));
}
// [[Rcpp::export]]
SEXP ext_ref_ex() {
std::vector<double> * x = new std::vector<double>(1000000);
SEXP xp = PROTECT(R_MakeExternalPtr(x, R_NilValue, R_NilValue));
R_RegisterCFinalizer(xp, finalize);
UNPROTECT(1);
return xp;
}
Сторона R:
library(Rcpp)
sourceCpp("tests.cpp")
# breaks and/or crashes
for(i in 1:10000) {
z <- ext_ref_ex()
}
# no issue
for(i in 1:10000) {
z <- ext_ref_ex()
rm(z)
gc()
}
При запуске первого цикла R в конечном итоге переходит в состояние ошибки после достаточного количества итераций (проблема# 1), в то время как ожидаемое поведение состоит в том, что данные должны быть очищены, и не должно быть никаких ошибок.
Проблема №2 в том, что если вы прервете процесс и вызовете gc()
, иногда память будет очищена, но обычно это не так.Согласно отчету htop
, R использует 60-70% памяти, даже после rm(list=ls())
и gc()
.
Во втором цикле нет проблем с памятью.
Я что-то не так делаю на стороне C?Я сталкиваюсь с ошибкой?
(R версия 3.5.2 Ubuntu 18.04 для Windows.)