1

in part of my code I need to optimize a function from Rcpp (I followed the 2nd answer here Applying the optim function in R in C++ with Rcpp). However, I found that the function leaks memory (very little, but it compounds if it's a part of repeatedly running simulation). I created a minimal reproducible example, but I have no idea where does the leak originate/how to deal with it. Could I ask for guidance on dealing with this issue?

Rcpp code:

#include <Rcpp.h>
using namespace Rcpp;
double objective_function(double x){
  double obj = .666 - x;
  return pow(obj, 2);
}
// [[Rcpp::export(leak)]]
double leak(double a, double b){
 

  // Extract R's optim function
  Rcpp::Environment stats("package:stats");
  Rcpp::Function optim = stats["optim"];
 
  // Call the optim function from R in C++
  Rcpp::List opt_results = optim(Rcpp::_["par"]    = .5,
                                 Rcpp::_["fn"]     = Rcpp::InternalFunction(&objective_function),
                                 Rcpp::_["method"] = "Brent",
                                 Rcpp::_["lower"]  = a,
                                 Rcpp::_["upper"]  = b);
 
  // Extract out the estimated parameter values
  double mu = opt_results[0];
 
  // Return estimated values
  return mu;
}

R code:

repeat{
  leak(0, 1)
}

When I look at my task manager, the RAM usage under Rstudio R Session is steadily increasing (which doesn't happen if I use any other function that just returns a value).

  • Does the leak also happen if you call `optim` directly in R, like normal? – Hong Ooi Oct 20 '20 at 19:21
  • That is a good question @HongOoi . I just tried optimizing the Rcpp defined function from R directly and the leak does not occur. It happens iff I optimize it from within the Rcpp leak function. – Frantisek Bartos Oct 21 '20 at 09:08

1 Answers1

2

Using macOS + the Instruments leak detector, it seems like Rcpp::InternalFunction is leaking:

Instruments leak detector

And this points us at the code here:

https://github.com/RcppCore/Rcpp/blob/97222bb753c4cd76a4cef7d33c2bfc2e305d1158/inst/include/Rcpp/generated/InternalFunction__ctors.h#L35-L38

Note that we're allocating an object with new, but we're also telling XPtr not to register a delete finalizer:

https://github.com/RcppCore/Rcpp/blob/97222bb753c4cd76a4cef7d33c2bfc2e305d1158/inst/include/Rcpp/XPtr.h#L88-L106

It's not immediately clear to me why we do this, but I think it explain the behavior. It could be worth filing an issue.

Kevin Ushey
  • 20,530
  • 5
  • 56
  • 88