Skip to content

Pipe can prevent GC of object if S3 method is used #229

Open
@wch

Description

@wch

The pipe can prevent GC of an object that's passed into it. It happens when:

  • The object is piped to a function
  • The function is an S3 method
  • The method returns a function (or something that captures the environment), and the result is saved

It seems that using the pipe causes there to be a reference to the object being piped

Here's an example where the use of %>% results in the object not being GC'd. However, if the function is called without the pipe, the object does get GC'd.

library(magrittr)
library(testthat)

f <- function(x, ...) {
  UseMethod("f")
}

f.default <- function(x, ...) {
  # Don't hold onto a reference to x
  rm(x)
  function() {
    123
  }
}

e <- new.env()
finalized <- FALSE
reg.finalizer(e, function(e) { finalized <<- TRUE; message("finalized") })

e1 <- e %>% f()
# If this line is used instead of the one above, then `gc()` collects `e` and finalizer runs.
# e1 <- f(e)

rm(e); gc(); gc()
expect_true(finalized)
#> Error: `finalized` isn't true.

# Clean up
rm(list=ls()); gc()
#> finalized

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions