[Rd] Objects not gc'ed due to caching (?) in R's S3 dispatch mechanism

luke-tierney at uiowa.edu luke-tierney at uiowa.edu
Thu Mar 29 17:37:06 CEST 2018


Now also committed to the release branch.

Best,

luke

On Tue, 27 Mar 2018, luke-tierney at uiowa.edu wrote:

> I have committed a change to R-devel that addresses this. To be on the
> safe side I need to run some more extensive tests before deciding if
> this can be ported to the release branch for R 3.5.0. Should know in a
> day or two.
>
> Best,
>
> luke
>
> On Tue, 27 Mar 2018, luke-tierney at uiowa.edu wrote:
>
>> This has nothing to do with printing or dispatch per se. It is the
>> result of an internal register (R_ReturnedValue) being protected. It
>> gets rewritten whenever there is a jump, e.g. by an explicit return
>> call. So a simplified example is
>> 
>> new_foo <- function() {
>>  e <- new.env()
>>    reg.finalizer(e, function(e) message("Finalizer called"))
>>      e
>>      }
>> 
>> bar <- function(x) return(x)
>> 
>> bar(new_foo())
>> gc() # still in .Last.value
>> gc() # nothing
>> 
>> UseMethod essentially does a return call so you see the effect there.
>> 
>> The R_ReturnedValue register could probably be safely cleared in more
>> places but it isn't clear exactly where. As things stand it will be
>> cleared on the next use of a non-local transfer of control, and those
>> happen frequently enough that I'm not convinced this is worth
>> addressing, at least not at this point in the release cycle.
>> 
>> Best,
>> 
>> luke
>> 
>> On Mon, 26 Mar 2018, Iñaki Úcar wrote:
>> 
>>> Hi,
>>> 
>>> I initially opened an issue in the R6 repo because my issue was with
>>> an R6 object. But Winston (thanks!) further simplified my example, and
>>> it turns out that the issue (whether a feature or a bug is yet to be
>>> seen) had to do with S3 dispatching.
>>> 
>>> The following example, by Winston, depicts the issue:
>>> 
>>> print.foo <- function(x, ...) {
>>>  cat("print.foo called\n")
>>>  invisible(x)
>>> }
>>> 
>>> new_foo <- function() {
>>>  e <- new.env()
>>>  reg.finalizer(e, function(e) message("Finalizer called"))
>>>  class(e) <- "foo"
>>>  e
>>> }
>>> 
>>> new_foo()
>>> gc() # still in .Last.value
>>> gc() # nothing
>>> 
>>> I would expect that the second call to gc() should free 'e', but it's
>>> not. However, if we call now *any* S3 method, then the object can be
>>> finally gc'ed:
>>> 
>>> print(1)
>>> gc() # Finalizer called
>>> 
>>> So the hypothesis is that there is some kind of caching (?) mechanism
>>> going on. Intended behaviour or not, this is something that was
>>> introduced between R 3.2.3 and 3.3.2 (the first succeeds; from the
>>> second on, the example fails as described above).
>>> 
>>> Regards,
>>> Iñaki
>>> 
>>> PS: Further discussion and examples in 
>>> https://github.com/r-lib/R6/issues/140
>>> 
>>> ______________________________________________
>>> R-devel at r-project.org mailing list
>>> https://stat.ethz.ch/mailman/listinfo/r-devel
>>> 
>> 
>> 
>
>

-- 
Luke Tierney
Ralph E. Wareham Professor of Mathematical Sciences
University of Iowa                  Phone:             319-335-3386
Department of Statistics and        Fax:               319-335-3017
    Actuarial Science
241 Schaeffer Hall                  email:   luke-tierney at uiowa.edu
Iowa City, IA 52242                 WWW:  http://www.stat.uiowa.edu


More information about the R-devel mailing list