Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is the destructor called when the CPython garbage collector is disabled?

I'm trying to understand the internals of the CPython garbage collector, specifically when the destructor is called. So far, the behavior is intuitive, but the following case trips me up:

  1. Disable the GC.
  2. Create an object, then remove a reference to it.
  3. The object is destroyed and the _____del_____ method is called.

I thought this would only happen if the garbage collector was enabled. Can someone explain why this happens? Is there a way to defer calling the destructor?

import gc
import unittest

_destroyed = False

class MyClass(object):

    def __del__(self):
        global _destroyed
        _destroyed = True

class GarbageCollectionTest(unittest.TestCase):

    def testExplicitGarbageCollection(self):
        gc.disable()
        ref = MyClass()
        ref = None
        # The next test fails. 
        # The object is automatically destroyed even with the collector turned off.
        self.assertFalse(_destroyed) 
        gc.collect()
        self.assertTrue(_destroyed)

if __name__=='__main__':
    unittest.main()

Disclaimer: this code is not meant for production -- I've already noted that this is very implementation-specific and does not work on Jython.

like image 848
Frederik Avatar asked Apr 05 '10 11:04

Frederik


People also ask

Does garbage collector call destructor?

What is Garbage Collector? Garbage collector looks for an instance/object which is not required anymore and treats these objects/instances as ready to destroy. Then, it makes a call to the destructor to release the memory and deallocate the resources.

Is destructor called automatically in Python?

Create Destructor using the __del__() MethodThis method is automatically called by Python when the instance is about to be destroyed. It is also called a finalizer or (improperly) a destructor.

Is destructor same as garbage collection?

The destructor is a special member function which is invoked when an object is destroyed. It is the last method run by a class. The garbage collector is part of the framework, automatically manages memory, and non-deterministically collects unreferenced objects to avoid memory leaks.

Which method is called when the object is to be destroyed?

A destructor method is called when all references to an object have been destroyed. In Python, the __del__() method is referred to as a destructor method. Destructors aren't as important in Python as they are in C++, because Python contains a garbage collector that takes care of memory management automatically.


1 Answers

Python has both reference counting garbage collection and cyclic garbage collection, and it's the latter that the gc module controls. Reference counting can't be disabled, and hence still happens when the cyclic garbage collector is switched off.

Since there are no references left to your object after ref = None, its __del__ method is called as a result of its reference count going to zero.

There's a clue in the documentation: "Since the collector supplements the reference counting already used in Python..." (my emphasis).

You can stop the first assertion from firing by making the object refer to itself, so that its reference count doesn't go to zero, for instance by giving it this constructor:

def __init__(self):
    self.myself = self

But if you do that, the second assertion will fire. That's because garbage cycles with __del__ methods don't get collected - see the documentation for gc.garbage.

like image 132
RichieHindle Avatar answered Nov 10 '22 09:11

RichieHindle