[PyKDE] Double free() problem in PyQt 3.15.1??

Phil Thompson phil at riverbankcomputing.co.uk
Sun Apr 23 11:07:40 BST 2006


On Saturday 22 April 2006 11:19 pm, Simon Edwards wrote:
> On Saturday 22 April 2006 21:17, Phil Thompson wrote:
> > On Saturday 22 April 2006 4:04 pm, Simon Edwards wrote:
> > > I'm confused as to what the newer exec_loop() code in QDialog was meant
> > > to do.
> > > ---------------------------------
> > > %If (Qt_3_0_0 -)
> > > 	int exec() /PyName=exec_loop, ReleaseGIL,
> > > 		    PreHook=__pyQtPreEventLoopHook__,
> > > 		    PostHook=__pyQtPostEventLoopHook__/;
> > >
> > > It looks like it is meant to take ownership away from the parent dialog
>
> and
>
> > > let Python handle destruction of the popup. But the dumpObjectTree()
> > > lines in my test code say that the parent dialog always keeps the popup
> > > on it's list of children objects.
> >
> > Correct.
> >
> > > When the parent dialog is destroyed so are the children objects. This
> > > is a problem if Python thinks that it should destroy the popup too.
> >
> > It's not a problem because QObject's dtor does the right thing in taking
> > itself out of any parent's list of children. In other words, it doesn't
> > matter (in the case of QObject and its subclasses) if both Python and C++
> > think they should call the dtor.
>
> I think I follow what you are saying. But that is only going to work
> correctly in the case of Python and Qt wanting to destroy the child dialog
> if Python calls the d'tor first. If the child dialog is destroyed by Qt
> when the parent dialog is destroyed, and THEN Python comes along later
> wanting to destroy the child dialog again, then it goes wrong.

This shouldn't matter. The "generated derived class" that SIP creates 
(sipKDialogBase in the output below) contains a dtor that will be invoked 
when the parent destroys it's children. It resets the pointer to the C++ 
instance in the Python object (see sip_api_common_dtor() in siplib.c) so that 
when the Python object gets garbage collected it knows the C++ instance has 
already been destroyed and doesn't try and do it again.

Phil

> valgrind output suggests that this is what is happening. The parent dialog
> is destroyed. The child dialog is destroyed at the same time. And then
> Python tries the child again. valgrind says that the illegal free/delete is
> coming from Python itself. (the first stack trace below) And is refering to
> memory that was free'd via Qt (the second stack trace).
>
> ---------------------------------------------------
> Double QObject deletion detected.
> ==7997==
> ==7997== Invalid free() / delete / delete[]
> ==7997==    at 0x401D268: operator delete(void*) (vg_replace_malloc.c:246)
> ==7997==    by 0x4E22609: QObject::~QObject() (in
> /usr/lib/libqt-mt.so.3.3.6) ==7997==    by 0x608452A: (within
> /usr/lib/python2.4/site-packages/kdeui.so) ==7997==    by 0x402A927:
> (within /usr/lib/python2.4/site-packages/sip.so) ==7997==    by 0x8089DDF:
> (within /usr/bin/python2.4)
> ==7997==    by 0x80FA46D: (within /usr/bin/python2.4)
> ==7997==    by 0x80B6FF5: PyEval_EvalFrame (in /usr/bin/python2.4)
> ==7997==    by 0x80B76BE: PyEval_EvalCodeEx (in /usr/bin/python2.4)
> ==7997==    by 0x80B7904: PyEval_EvalCode (in /usr/bin/python2.4)
> ==7997==    by 0x80D946B: PyRun_FileExFlags (in /usr/bin/python2.4)
> ==7997==    by 0x80D970B: PyRun_SimpleFileExFlags (in /usr/bin/python2.4)
> ==7997==    by 0x8055B02: Py_Main (in /usr/bin/python2.4)
> ==7997==    by 0x4080EA1: __libc_start_main
> (in /lib/tls/i686/cmov/libc-2.3.6.so)
>
>
> ==7997==  Address 0x56CFFE0 is 0 bytes inside a block of size 2,044 free'd
> ==7997==    at 0x401D268: operator delete(void*) (vg_replace_malloc.c:246)
> ==7997==    by 0x6073D6B: sipKDialogBase::~sipKDialogBase()
> (in /usr/lib/python2.4/site-packages/kdeui.so)
> ==7997==    by 0x608452A: (within
> /usr/lib/python2.4/site-packages/kdeui.so) ==7997==    by 0x402A927:
> (within /usr/lib/python2.4/site-packages/sip.so) ==7997==    by 0x8089DDF:
> (within /usr/bin/python2.4)
> ==7997==    by 0x80FC987: (within /usr/bin/python2.4)
> ==7997==    by 0x4029030: (within /usr/lib/python2.4/site-packages/sip.so)
> ==7997==    by 0x607840C: sipKDialogBase::removeChild(QObject*)
> (in /usr/lib/python2.4/site-packages/kdeui.so)
> ==7997==    by 0x4E22AA8: QObject::~QObject() (in
> /usr/lib/libqt-mt.so.3.3.6) ==7997==    by 0x4E5D05C: QWidget::~QWidget()
> (in /usr/lib/libqt-mt.so.3.3.6) ==7997==    by 0x4FD7A07:
> QDialog::~QDialog() (in /usr/lib/libqt-mt.so.3.3.6) ==7997==    by
> 0x4916B05: sipQDialog::~sipQDialog()
> (in /usr/lib/python2.4/site-packages/qt.so)
> ==7997==    by 0x491DF56: (within /usr/lib/python2.4/site-packages/qt.so)
> ==7997==    by 0x402A927: (within /usr/lib/python2.4/site-packages/sip.so)
> ==7997==    by 0x8089DDF: (within /usr/bin/python2.4)
> ==7997==    by 0x807A2D4: (within /usr/bin/python2.4)
> ==7997==    by 0x402A8A4: (within /usr/lib/python2.4/site-packages/sip.so)
> ==7997==    by 0x402A8E0: (within /usr/lib/python2.4/site-packages/sip.so)
> ==7997==    by 0x8089DDF: (within /usr/bin/python2.4)
> ==7997==    by 0x80FA46D: (within /usr/bin/python2.4)
> ==7997==    by 0x80B6FF5: PyEval_EvalFrame (in /usr/bin/python2.4)
> ==7997==    by 0x80B76BE: PyEval_EvalCodeEx (in /usr/bin/python2.4)
> ==7997==    by 0x80B7904: PyEval_EvalCode (in /usr/bin/python2.4)
> ==7997==    by 0x80D946B: PyRun_FileExFlags (in /usr/bin/python2.4)
> ==7997==    by 0x80D970B: PyRun_SimpleFileExFlags (in /usr/bin/python2.4)
> ==7997==    by 0x8055B02: Py_Main (in /usr/bin/python2.4)
> ==7997==    by 0x4080EA1: __libc_start_main
> (in /lib/tls/i686/cmov/libc-2.3.6.so)
> ---------------------------------------------------




More information about the PyQt mailing list