2

I read objgraph document recently, and I confused about the following code

>>> class MyBigFatObject(object):
...     pass
...
>>> def computate_something(_cache={}):
...     _cache[42] = dict(foo=MyBigFatObject(),
...                       bar=MyBigFatObject())
...     # a very explicit and easy-to-find "leak" but oh well
...     x = MyBigFatObject() # this one doesn't leak

It show that "a very explict and easy-to-find 'leak'". Do this has memory leak? Is it the dict _cache?

ali_m
  • 71,714
  • 23
  • 223
  • 298
john2000
  • 75
  • 7
  • 1
    its not a leak, its because there's always a reference to `_cache` as long as `computate_something` is in scope, so it will always remain in memory – GP89 Jul 27 '12 at 08:54

2 Answers2

7

_cache is a keyword argument with a mutable default, which is indeed mutated in the function body. This'll store MyBigFatObjects instances permanently in that mutable keyword argument.

This is not so much a leak as a misunderstanding of the longevity of mutable keyword arguments. The function itself could still call del _cache[42] to delete these objects.

See "Least Astonishment" and the Mutable Default Argument for more information on the subject.

Community
  • 1
  • 1
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
1

As dict is mutable, the changes made in it will affect also the caller, so the reference to two MyBigFatObject will be kept.

You should explicitly delete it (del _cache[42]), o rather make changes in own copy of dictionary or any other mutable object (you can use copy module for that).

Michal Čihař
  • 9,799
  • 6
  • 49
  • 87