Package: python-qt3 Version: 3.13-4 Severity: normal Followup-For: Bug #293087
This test and others that I did where wrong because: 1- If QDialog or another graphical Qt class is used to instantiate the test objects, then you must insert a QApplication::processEvents() call in the loop, because there is memory allocated with Xlib that isn't deallocated if there isn't any event processing (this is what qt-bugs folks said to me). 2- The instantiated objects must have parent == None, because if you use parent == the Main Window, then the objects are only destroyed when Main Window dies, this is the correct behaviour by PyQT design. This doesn't apply to the C++ test. After having that two issues in consideration, I got a non-leaking C++ test and a python test that _leaks_ with this Debian packaged PyQT version, but _dont leaks_ with the latest Sip/PyQT snapshot. So the solution seems to be upgrading this package to the latest PyQT snapshot. I'm attaching the latest Python and C++ tests. Thanks for your help. -- System Information: Debian Release: testing/unstable APT prefers unstable APT policy: (500, 'unstable') Architecture: i386 (i586) Kernel: Linux 2.6.8nah1-k6 Locale: LANG=C, LC_CTYPE=C Versions of packages python-qt3 depends on: ii python 2.3.3-7 An interactive high-level object-o ii python2.3-qt3 3.13-4 Qt3 bindings for Python 2.3 -- no debconf information
#include <qapplication.h> #include <qmainwindow.h> #include <qdialog.h> #include <qevent.h> #include <qfile.h> #include <qpushbutton.h> #include <iostream> class Main : public QMainWindow { public: void keyPressEvent( QKeyEvent *k); }; QApplication *app; void presentMemData() { QFile f("/proc/self/status"); QTextStream stream(&f); QString line; QStringList l; int vmsize = 0, vmrss = 0; f.open(IO_ReadOnly); while ( !stream.eof() ) { line = stream.readLine(); l = QStringList::split(" ", line); if (l.size() > 1) { if (line.startsWith("VmSize:")) vmsize = l[1].toInt(); if (line.startsWith("VmRSS:")) vmrss = l[1].toInt(); } } f.close(); std::cout << "* VmSize: " << vmsize << "; VmRss: " << vmrss << std::endl; } void Main::keyPressEvent(QKeyEvent *k) { if (k->key() == QKeyEvent::Key_Enter || k->key() == QKeyEvent::Key_Return) { std::cout << "Creating QDialog's" << std::endl; for(int i=0;i<80001;++i) { // Note, if you change this for a QPushButton instead // of a QDialog, it also leaks! // but no for a QCustomEvent! QDialog *d = new QDialog(this); delete d; if(i%1000 == 0) { std::cout << "Pre processEvents()" << std::endl; presentMemData(); app->processEvents(); std::cout << "Post processEvents()" << std::endl; } } } } int main(int argc, char **argv) { app = new QApplication(argc, argv); Main w; app->setMainWidget(&w); w.show(); std::cout << "QT Version: " << qVersion() << std::endl; std::cout << "Focus the Window and press Enter for object creation / destruction loop" << std::endl; app->exec(); std::cout << "Pre deleting QApplication" << std::endl; presentMemData(); delete app; std::cout << "Post deleting QApplication" << std::endl; presentMemData(); return 1; }
#!/usr/bin/python import os, sys, time, gc from qt import * def report(s): print s sys.stdout.flush() def presentMemData(s=""): vmsize = vmrss = 0 for l in open('/proc/self/status','r').readlines(): if l.startswith('VmSize:'): vmsize = int(l.split()[1]) elif l.startswith('VmRSS:'): vmrss = int(l.split()[1]) report(s+"* VmSize: %d VmRss: %d" % (vmsize,vmrss)) class Main(QMainWindow): def __init__(self): QMainWindow.__init__(self) def keyPressEvent(self, event): global app NUM_FORMS = 4000 k = event.key() if k in (QKeyEvent.Key_Enter, QKeyEvent.Key_Return): while 1: report("\n*** Creating %d QDialog's" % NUM_FORMS) presentMemData("Pre-Creating: \n") for x in range(NUM_FORMS): # Using QString("12345678") or QCustomEvent(1) also # leaks f = QDialog() f = None report("End Creating\nForcing GC") col = gc.collect() uncol = len(gc.garbage) if col or uncol: report("GC Collected: %d Uncollected: %d" % (col, uncol)) report("End GC") presentMemData("Post-Creating: \n") app.processEvents() presentMemData("Post QApplication::processEvents(): \n") elif k == QKeyEvent.Key_M: presentMemData() app = QApplication(sys.argv) w = Main() app.setMainWidget(w) w.show() report("QT Version: "+ qVersion()) report("PYQT Version: "+ PYQT_VERSION_STR) report("SIP Version: "+ os.popen('sip -V').read()) report("Focus the Window and press Enter for object creation / destruction loop\n") presentMemData() app.exec_loop()
test_cpp_leak: test_cpp_leak.cpp g++ -g -o test_cpp_leak test_cpp_leak.cpp -I/usr/share/qt3/include -lqt-mt