[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