[PyQt] Again, problems with garbage collection

Martin Teichmann lkb.teichmann at gmail.com
Fri Mar 19 11:27:59 GMT 2010


Hi List, Hi Phil,

>> I just upgraded to PyQt4 4.7.2 (with Python 2.6.4 on Windows XP)
>> and the following little script crashes with "unterlying C/C++ object
>> has been deleted"
>>
>> I guess that's a bug.
>
> Why? It works as I would expect.

Oops. I didn't realize that that's a excpected behaviour. I was under the
impression that Qt shouldn't "own" objects and delete them, so that
this runtime error was always indicator of a bug (or an indicator that
someone forgot to call the parent's __init__, maybe the error message
should actually read "underlying C/C++ object has been deleted or not
yet created", anyhow, that's not the current problem)

Unfortunately, this leads to the somewhat annoying behaviour that
signals are still sent to C++-dead but python-alive objects. That's
especially annoying when the python object ought to be dead already,
just had not been collected yet, as illustrated in the following
example. Note how gc.collect makes a difference, a situation that
better should not happen as garbage collection happens at random intervals...

Greetings

Martin

And here the example:

---------------------- snip -----------------------------
from PyQt4.QtCore import QObject, SIGNAL, QCoreApplication
import gc

# following two lines not important
from sys import argv
app = QCoreApplication(argv)

class A(QObject):
    def __init__(self, p=None):
        QObject.__init__(self, p)

    def g(self):
        self.emit(SIGNAL("sig"))

    def k(self):
        self.emit(SIGNAL("kill"))

    def f(self):
        try:
            print self.children() # only to test if C++ object is still alive
        except RuntimeError:
            print "hey, caught runtime error!"

    def kill(self):
        self.setParent(None)

a = A()
b = A(a)
c = A(b)

b.connect(a, SIGNAL("sig"), c.f)
b.connect(a, SIGNAL("kill"), b.kill)

a.g() # deliver signal to c, all fine
c.v = c # create cycle to prevent immediate collection
b = None
c = None
a.k() # now c ceases existence in the C++ world
print "here"
a.g() # signal is still delivered
print "now collect"
gc.collect()
a.g() # signal no more delivered, python object has died
---------------------------- snip -----------------------------------------


More information about the PyQt mailing list