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

Reply via email to