[PyQt] memory leak using QMainWindow.removeToolBar
Baz Walter
bazwal at ftml.net
Mon Aug 16 23:31:33 BST 2010
On 16/08/10 18:27, danny wrote:
> Howdy,
>
> I have run into this curious problem that I think is caused by a memory leak
> or improper reference counting related to toolbars in QMainWindow.removeToolBar.
> The problem appears when you remove a toolbar but keep an instance variable
> maintaining a reference to the toolbar. I am aware that removeToolBar only
> hides the toolbar and does not delete it. I also am aware that the following
> code may seem foolish, but it does show the bug. The code below is a minimal
> example demonstrating the problem. It is 34 lines long. Simply run the app, and
> close via the close box. The app will not close gracefully, but rather seg fault.
> This has been validated on windows and Linux. I don't believe the following
> code is doing anything stupid enough to justify a seg fault. The problem
> disappears is you remove the instance reference to the toolbar
> (self.editToolBar = editToolBar). Notice that the code is intended to reside
> within an SDI framework app like Mark Summerfield uses in his excellent PyQT
> book. The instances variables probably keep additional references around that
> are part of the problem. Explicitly removing the attribute, gets rid of the
> problem.
>
> Included below is the source code. Please let me know if this is a bug or
> my own stupidity.
>
> I am running python 2.5.1, pyqt 4.7.3
>
> thanks,
>
> Danny
>
> #%<--------------------------------------------
> import sys
> from PyQt4 import QtGui, QtCore, QtSql
>
> def isAlive(qobj):
> import sip
> try:
> sip.unwrapinstance(qobj)
> except RuntimeError:
> return False
> return True
>
> class MyApp(QtGui.QMainWindow):
> NextId = 1
> Instances = set()
>
> def __init__(self, parent=None):
> super(MyApp, self).__init__(parent)
> self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
> MyApp.Instances.add(self)
> self.editToolBar = self.addToolBar("Edit")
> self.removeToolBar(self.editToolBar)
> # delattr(self, 'editToolBar') # this gets rid of the seg fault
> self.destroyed.connect(MyApp.updateInstances)
> self.setCentralWidget(QtGui.QWidget())
>
> @staticmethod
> def updateInstances(qobj):
> MyApp.Instances = set([window for window \
> in MyApp.Instances if isAlive(window)])
>
> if __name__=='__main__':
> application = QtGui.QApplication(sys.argv)
> MyApp().show()
> application.exec_()
i don't think it is a bug. the real problem is with how the toolbar is
being created, not with how it's being destroyed.
try something like this:
import sys
from PyQt4 import QtGui, QtCore
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QMainWindow.__init__(self, parent)
self._toolbar = QtGui.QToolBar('Edit', self)
self.addToolBar(self._toolbar)
self.removeToolBar(self._toolbar)
if __name__=='__main__':
app = QtGui.QApplication(sys.argv)
win = MainWindow()
win.show()
sys.exit(app.exec_())
More information about the PyQt
mailing list