<br><br><div class="gmail_quote">On Thu, Aug 5, 2010 at 03:43, Phil Thompson <span dir="ltr"><<a href="mailto:phil@riverbankcomputing.com">phil@riverbankcomputing.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
On Thu, 5 Aug 2010 03:10:50 -0400, Luke Campagnola<br>
<<a href="mailto:lcampagn@email.unc.edu">lcampagn@email.unc.edu</a>><br>
wrote:<br>
<div><div></div><div class="h5">> I believe I have run into a class of bugs in PyQt4. I originally found<br>
that<br>
> QSpinBox.lineEdit() returns a QLineEdit instance which does not maintain<br>
> its<br>
> reference count properly after the original QSpinBox is deleted. Thus it<br>
is<br>
> possible to either 1) have uncollectable LineEdits lingering in memory,<br>
or<br>
> 2) crash the program by accessing the LineEdit (see example below).<br>
><br>
> The same bug also applies to:<br>
> - QAbstractSpinBox.lineEdit<br>
> - QComboBox.lineEdit,<br>
> - QAbstractScrollArea.horizontalScrollBar<br>
> - QAbstractScrollArea.verticalScrollBar<br>
> - QTreeView.header<br>
> - QSplitter.handle<br>
><br>
> .. and likely many others. In the best case, this bug causes minor<br>
memory<br>
> leaks that few people are likely to notice. In the worst case, it causes<br>
> crashes which are very difficult to debug if you don't have easy access<br>
to<br>
> debugging symbols (ie using windows binaries).<br>
><br>
> $ python<br>
>>>> from PyQt4.QtGui import *<br>
>>>> a = QApplication([])<br>
>>>> s = QSpinBox()<br>
>>>> l = s.lineEdit()<br>
>>>> del s<br>
>>>> l.text()<br>
> Segmentation fault<br>
<br>
</div></div>These are refer to objects created (and still owned) by C++. They are<br>
destroyed by C++ when (for example) the QSpinBox is deleted. There is<br>
nothing that can be done about that.<br></blockquote><div><br></div><div><div>Agreed; Qt may delete objects whenever it pleases. The real issue is that 1) the reference count for these objects is incorrect, causing memory leaks, and 2) the object is not informed when it's underlying C++ object is deleted, which raises the possibility of crashes (raising an exception would be perfectly acceptable). The former issue is unavoidable, and the latter (in my opinion) is a serious problem affecting the usability of PyQt. There are a few rare instances when I think a segmentation fault through python is acceptable; this is not one of them.</div>
</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">Because they are created by C++, PyQt cannot (easily) work out when they<br>
get deleted. If it could then you would get an exception about the C++<br>
object no longer existing instead of a crash.</blockquote><div><div><br></div><div>Given that the original SpinBox object had the correct reference count and knew when the underlying object had been deleted, there should be a way to accomplish the same behavior with the LineEdit. I am not familiar with sip internals, but it seems this could be done by wrapping the SpinBox.lineEdit function to ensure that the returned object is configured properly, or the SpinBox itself could call sip.setdeleted on the LineEdit as soon as the underlying object is deleted. My current workaround is to call sip.setdeleted from within SpinBox.__del__, but this is obviously not guaranteed to be called after the underlying object is deleted.</div>
<div><br></div><div>Luke</div></div></div>