[PyQt] How SIP detects that a QObject need to destruct.

Phil Thompson phil at riverbankcomputing.com
Thu Mar 29 12:47:54 BST 2012

On Thu, 29 Mar 2012 19:22:10 +0800, Goldfish Huang <hgoldfish at gmail.com>
> Hi, all.
> I am doubted how  SIP deal with QObject's cycle reference, when I try
> to fix some unknown memory leaks. It seems that SIP only keep a
> reference to QObject, whatever how many children it has. Then a
> QObject must have not less than 2 reference count, one from Python and
> another from SIP. The question is, when I delete the QObject from
> Python, how SIP detects that and decrease the reference? It supposed
> that the reference count will be decreased to 1, and never destructed.
> The code pastes below:
>     import sys, gc
>     from PyQt4.QtCore import *
>     gc.disable()
>     c=QObjectCleanupHandler()
>     o1=QObject()
>     QObject(o1), QObject(o1)
>     c.add(o1)
>     print sys.getrefcount(o1) , len(o1.children())
>     #delete a child but the reference count remains 2.
>     o1.children()[0].setParent(None)
>     print sys.getrefcount(o1) , len(o1.children())
>     #decrease reference count of o1 by one.
>     del o1
>     #It is destructed!
>     print c.isEmpty()

I think you are getting confused by the behaviour of sys.getrefcount().
This will never return a value less than 2 because it includes the extra
reference that is its argument - in other words always subtract 1 from the
value it returns to see how many references there really are. In this case
there is only ever one reference to o1 until you del it. Because o1 doesn't
have a parent then sip calls the C++ dtor when the Python object is
destroyed. QObjectCleanupHandler notices when the C++ QObject is deleted.


More information about the PyQt mailing list