[PyQt] sip segfault in disconnectNotify

Phil Thompson phil at riverbankcomputing.com
Fri Sep 10 21:20:32 BST 2010


On Fri, 10 Sep 2010 18:55:17 +0200, Erik Janssens
<Erik.Janssens at conceptive.be> wrote:
> Hello Phil,
> 
> I've made a unittest for the segfault, it is ran by
> executing the command :
> 
> python -m nose.core test_qt_bindings.py
> 
> It seems to be a matter of keeping too much references,
> rather than keeping not enough references.
> 
> I know the code in itself is pointless and simply
> removing a line in it ensures that it doesn't segfaults,
> but I would like to understand why it segfaults.

I think this is what's happening...

If you replace the line "self.table = table" to "self.widget = table" then
it doesn't segfault. The only thing that can be affected by such a change
is the order in which the values of the instance dictionary get garbage
collected (because you have changed the keys and hence the layout of the
dict's hash table).

I think that the model is being garbage collected (and it's C++ dtor being
called) while it is still being used by the C++ QTableView. Although the
reference counts ensure that the Python objects get garbage collected in
the "right" order (ie. the Python TableModelSubclass instance will not get
garbage collected until after the Python QTableView instance) it doesn't
follow that the C++ dtors are called in the same order.

In this case Python doesn't own the C++ QTableView (because it has a
parent) but it does own the underlying C++ QStringListModel. Therefore the
QTableView dtor isn't called when the Python QTableView object is garbage
collected, but the QStringListModel dtor is called when the Python
TableModelSubclass instance is garbage collected. 

There are two approaches to working around this (apart from avoiding
complex inter-instance references in the first place)...

- Explicitly remove problematic references at appropriate places, ie.
establish an order in which things will get garbage collected.
Unfortunately it can be difficult to work out exactly what and where the
right places are.

- Pass responsibility to Qt by, in this case, creating the model with an
appropriate parent.

Ultimately I think this is a Qt bug. It should use a QPointer to guard the
pointer to the QAbstractItemModel from the QAbstractItemView so that it can
properly cope with the model disappearing.

Phil


More information about the PyQt mailing list