if (xd->magic != CAIROGD_MAGIC)
error("Not a Cairo device");
endif
if (xd && xd->cb) {
SEXP old = xd->cb->onSave;
if (!old) old = R_NilValue;
if (fn != R_NilValue) {
R_PreserveObject(fn);
xd->cb->onSave = fn;
} else xd->cb->onSave = 0;
if (old != R_NilValue)
R_ReleaseObject(old);
return old;
}
}
}
Rf_error("Not a valid Cairo device");
return R_NilValue;
}
On Cairo/src/cairotalk.c, CairoGD_Close does not seem release that protected function object at the end. Since R put protected object into a stack, missing one release call would leave the object on the bottom of stack which could be a much bigger R object. So, the memory leak could be large. We add an explicit object release (shown below) and then find the memory leak becomes no longer detected.
Hi,
When using R Cairo package onSave function, we detect some memory leak on R object. The issue seems coming from CairoGD_Close function.
On Cairo/src/cairogd.c, Cairo_set_onSave() sets onSave function a protected R object (Line 544)
SEXP Cairo_set_onSave(SEXP dev, SEXP fn) { int devNr = asInteger(dev) - 1; GEDevDesc gd = GEgetDevice(devNr); if (gd) { NewDevDesc dd = gd->dev; if (dd) { CairoGDDesc xd = (CairoGDDesc ) dd->deviceSpecific;
ifdef USE_MAGIC
endif
}
On Cairo/src/cairotalk.c, CairoGD_Close does not seem release that protected function object at the end. Since R put protected object into a stack, missing one release call would leave the object on the bottom of stack which could be a much bigger R object. So, the memory leak could be large. We add an explicit object release (shown below) and then find the memory leak becomes no longer detected.
static void CairoGD_Close(NewDevDesc dd) { CairoGDDesc xd = (CairoGDDesc *) dd->deviceSpecific; if(!xd || !xd->cb) return;
xd->cb->save_page(xd->cb,xd->npages); if (xd->cb->onSave) { SEXP devNr = PROTECT(ScalarInteger(ndevNumber(dd) + 1)); SEXP pageNr = PROTECT(ScalarInteger(xd->npages + 1)); eval(lang3(xd->cb->onSave, devNr, pageNr), R_GlobalEnv); UNPROTECT(2); /* Add object release call to onSave, otherwise, memory would leak */ R_ReleaseObject(xd->cb->onSave); } xd->cb->destroy_backend(xd->cb);
free(xd); dd->deviceSpecific=NULL; }
We would like you to know of this finding. If you think this is an issue, could you consider fixing it in a new version.
Thanks,
Qin