[PyQt] Help tracking down intermittent segfault using QGraphicsItem

Mathias.Born at gmx.de Mathias.Born at gmx.de
Sat Jan 5 23:04:03 GMT 2013


On 05.01.2013, 22:58:28 Andreas Pakulat wrote:
> Hi,

> Am Samstag, 5. Januar 2013 schrieb :
> On 05.01.2013, 16:50:29 Andreas Pakulat wrote:
> [...]
>> Often a segfault is caused by using a pointer (in C++) which points to
>> a memory location thats not valid anymore, for example because the
>> object has been deleted already. In the context of PyQt this can
>> happen when you stop keeping references to objects that or instances
>> of C++-provided classes in python. In such a case the C++ parts of the
>> object will be deleted and thus any other C++ code that has a
>> reference to the object will crash when it tries to access the object.
>> I think thats the most common problem one encounters with PyQt4.

> While this is certainly true in general, I'd say that sip goes to
> great length in order to avoid that kind of crash by carefully
> observing who owns what. It is aware of the parent-child memory
> management of Qt. A python program should never be able to cause a
> crash. Is there any place in PyQt where the Python code has to keep
> references to keep the program going?

> Thats not always possible, it only works for objects which tell sip
> when they are deleted, for example QObject instances. Other Qt types
> do not support object life tracking like QObject, so sip has no way
> to know that it should not delete the object when the python reference is garbage collected.

That's why you have to specify ownership in sip files and when using
sip from the C++ side. sip doesn't actually track anything. If an
object is owned by the Python side, the wrapped C++ part is destroyed
when the reference count of the wrapper becomes zero. If it is owned
by C++, the wrapper is deleted, but the C++ object stays alive.

Erik Janssens posted this example:

from PyQt4 import QtGui
app = QtGui.QApplication([])
window = QtGui.QMainWindow()
statusbar = window.statusBar()
del window
statusbar.objectName()

which causes a crash in the last line, because "window" is gone along
with the real (C++)statusbar, but the Python wrapper "statusbar" still
exists without its C++ counterpart. That's because the QMainWindow instance
is created by Python and thus owned by Python.

In qmainwindow.sip:

QStatusBar *statusBar() const /Transfer/;

where "/Transfer/" means:

"In the case of methods returned values (unless they are new references to already
wrapped values) are normally owned by C++ anyway. However, in addition, an association
between the returned value and the instance containing the method is created with
regard to the cyclic garbage collector." (from the docs)

If "statusbar" were given an extra reference to "window", the crash could be avoided,
but then "del window" would not delete the window anymore. This would be safer,
but sip currently doesn't do that.

Best Regards,
Mathias Born



More information about the PyQt mailing list