Join GitHub today
GitHub is home to over 50 million developers working together to host and review code, manage projects, and build software together.
Sign upR6 constructor creating persistent reference to arguments #121
Comments
|
Thanks for finding this bug. I think this is happening because the finalizer is capturing the parent environment. Here's a modified example that uses R's library(R6)
A <- R6::R6Class(
"A",
public = list(
value = NULL,
initialize = function(value) {
self$value <- value
}
)
)
B <- R6::R6Class(
"B",
public = list(
initialize = function(a) {
message(sprintf("I was passed %s in constructor", a$value))
}
)
)
a <- A$new(1)
reg.finalizer(a, function(e) message("Deleting object A"))
b <- B$new(a)
reg.finalizer(b, function(e) message("Deleting object B"))
rm(a)
gc()
# Deleting object A
rm(b)
gc()
# Deleting object BHere's the part where the finalizer captures the parent environment. It happens because the The fix should be pretty straightforward. |
|
Thanks - this is great. I can confirm things working as expected with the update, too :) |
I'm not sure this is exactly a bug, but this is behaviour that surprised me. When passing an object through the constructor of an R6 object, the object passed as an argument will not be garbage collected until the newly created object is garbage collected.
Here is a minimal example:
Create a copy of
Aand pass that through toBwhich just ignores the argumentDeleting
ashould (to my intuition anyway) leave no references toabut the finalizer is not called...until
bis deleted and garbage collected:I've poked about but I can't work out what environment a reference to
Ais being kept. This works the same way withcloneableset toTRUEorFALSE, and the behaviour is the same for non-portable classesIn the end, nothing is terrible - things get deleted eventually. But it's a bit of a problem for a DB wrapper I am writing as it's overly conservative about when things can be deleted.