Trolltech Home | Qt-interest Home | Recent Threads | All Threads | Author | Date
All threads index page 4

Qt-interest Archive, January 2007
QTreeWidget client memory management


Message 1 in thread

Hi all,

I'm experimenting with Valgrind and Qt4, in the hope that it will help me 
avoid nasty problems as I improve my understanding.  :-)

I have a class derived from QTreeWidget and it holds a fair amount of data 
throughout the programme lifetime.  This is because the user needs access to 
the data at all times.  At programme close I would like "to do the right 
thing" in terms of releasing resources, so that I know I am doing right in 
other situations when I destroy things earlier on.  

When I run valgrind --tool=memcheck with memcheck=full and show reachable=yes 
I get the (showing only tail of) output below.  I'm drawn to the large volume 
of bytes reported under "still reachable".

The Valgrind docs suggest that "still reachables" are a symptom of programmer 
sloppiness, but go on to suggest that these occurrences are frequent and 
arguably unimportant.  Hmmm.

As far as I can see I am correctly using QTreewidget; anything I create with 
new is a child of a toplevel item and in the class destructor I call 
QTreeWidget::clear() in the belief that this ensures correct tidy up.  That 
doesn't seem to change the Valgrind verdict though.

Can anyone offer any insight into what is going on here? Have I misunderstood 
how to clean up after QTreeWidget?

Regards,



Amit


************** post change extract ***************

==6537== 
==6537== 12,846,490 bytes in 174,379 blocks are still reachable in loss record 
259 of 259
==6537==    at 0x4021259: malloc 
(in /usr/lib/valgrind/x86-linux/vgpreload_memcheck.so)
==6537==    by 0x4A3314C: qMalloc(unsigned) (qglobal.cpp:1802)
==6537==    by 0x4597D39: ??? (qvector.h:336)
==6537==    by 0x4598151: ??? (qvector.h:271)
==6537==    by 0x4590FED: QTreeWidgetItem::insertChild(int, QTreeWidgetItem*) 
(qtreewidget.cpp:1647)
==6537==    by 0x4591160: QTreeWidgetItem::addChild(QTreeWidgetItem*) 
(qtreewidget.cpp:1609)
==6537==    by 0x4592D5B: QTreeWidgetItem::QTreeWidgetItem(QTreeWidgetItem*, 
int) (qtreewidget.cpp:1309)
==6537==    by 0x818B17B: Tree::parseWholeLine(QString const&) 
(stdavailabilitytree.cpp:599)
==6537==    by 0x818CE2A: Tree::readAvailabilityData(QString const&) 
(stdavailabilitytree.cpp:181)
==6537==    by 0x818DF1A: Tree::Tree(QString const&, QWidget*) 
(stdavailabilitytree.cpp:110)
==6537==    by 0x80AB6EE: mainwindow::mainwindow(Relay*, QWidget*, 
QFlags<Qt::WindowType>) (kf3mainwindow.cpp:167)
==6537==    by 0x80B6D6E: main (main.cpp:71)
==6537== 
==6537== LEAK SUMMARY:
==6537==    definitely lost: 1,325 bytes in 52 blocks.
==6537==    indirectly lost: 9,456 bytes in 155 blocks.
==6537==      possibly lost: 4,424 bytes in 4 blocks.
==6537==    still reachable: 24,553,580 bytes in 641,842 blocks.
==6537==         suppressed: 0 bytes in 0 blocks.



--
 [ signature omitted ] 

Message 2 in thread

Hi,

> Can anyone offer any insight into what is going on here? Have I misunderstood 
> how to clean up after QTreeWidget?

It's hard to tell what is going wrong. We'd have to see how you're using 
QTreeWidget. A small compilable example reproducing the problem would be 
fine.

--
 [ signature omitted ] 

Message 3 in thread

Dimitri,

thanks for the suggestion.  This cut down version behaves the same way in 
Valgrind as the larger programme ("unreachables") although the volume is 
lower because I've included a much smaller datafile (the *.csv).

I use this approach to allow users to view the tree from a menu, as per this 
example extract.  But in the full app, I also use the public interface of the 
tree to allow its use as a "model" for a more complex form.  

It will benefit from a re-write along model/view lines - planned.

Regards,


Amit

On Sunday 21 January 2007 08:30, Dimitri wrote:
>
> It's hard to tell what is going wrong. We'd have to see how you're using
> QTreeWidget. A small compilable example reproducing the problem would be
> fine.
>

Attachment:

Attachment: memMgtQuery.zip
Description: Zip archive


Message 4 in thread

Hi,

> thanks for the suggestion.  This cut down version behaves the same way in 
> Valgrind as the larger programme ("unreachables") although the volume is 
> lower because I've included a much smaller datafile (the *.csv).

I ran this program under Valgridn on a Fedora core 6 Linux distribution.

I was unable to see any memory leaks related to QTreeWidgetItem.

--
 [ signature omitted ] 

Message 5 in thread

Dimitri,

sorry - I seem to have confused myself on cause.  In earlier Valgrind runs I 
did have unreachables which mentioned my Tree class.  But they do indeed seem 
to be missing from the smaller programme.  I think I must have been focusing 
too closely on the numbers at the expense of the words :-(

Are you saying you got no leak reports at all (no unreachables, no defintely 
lost) or just that the Tree class is not the cause?

I still see a residual report of "54,752 bytes in 1093 blocks are still 
reachable in loss record 129."  These seem to reference main, QApplication 
and FcInit along the way.  

A








On Monday 22 January 2007 21:15, Dimitri wrote:
>
> I ran this program under Valgridn on a Fedora core 6 Linux distribution.
>
> I was unable to see any memory leaks related to QTreeWidgetItem.
>
> --
> Dimitri
>
> --
> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx with
> "unsubscribe" in the subject or the body. List archive and information:
> http://lists.trolltech.com/qt-interest/

--
 [ signature omitted ] 

Message 6 in thread

Amazing the power of fresh air...I can answer some of my own question today.

Of 24m bytes of still "reachables" circa 90% were down to components which 
were create with new when setting up the mainwindow but lacked a 
corresponding delete in the destructor.  I suspect that a large part of the 
remained is down to QActions & menus, and I am confident I can now deal with 
these.

I am still puzzled that the act of clearing the QTreeWidget didn't seem to 
release the resources but deleting higher life forms does.  Does this 
correspond to others' experience?

The remainder of my error reports seem to be "Conditional jump or move depends 
on unitialised value(s)." I have > 100 of these.  They seem to largely relate 
to widget drawing operations.  At the head of my output there is a hint that 
I may have hidden issues with a stackwidget and a QPixmap.  Is this level of 
error reporting usual in Qt4 apps or is it more likely me?  [I know where my 
money is....it is usually me!]  Am including a couple of reports (below) in 
case anyone can offer hints on tracing to source.


** Qmake settings for gcov / gprof **

For anyone else using GNU profiling tools with Qmake for the first time here 
is what I found to work in .pro for enabling gcov & gprof:

QMAKE_CXXFLAGS += -fprofile-arcs -ftest-coverage -pg
QMAKE_LIBS+= -lgcov -pg

Regards,


Amit

** Valgrind Extract **

--5349-- Reading syms 
from /usr/local/Trolltech/Qt-4.2.1/plugins/imageformats/libqsvg.so 
(0x5AAD000)
--5349-- Reading debug info 
from /usr/local/Trolltech/Qt-4.2.1/plugins/imageformats/libqsvg.so.debug...
--5349--    object doesn't have a symbol table
--5349-- Reading syms from /usr/local/Trolltech/Qt-4.2.1/lib/libQtSvg.so.4.2.1 
(0x5B9B000)
--5349-- Reading debug info 
from /usr/local/Trolltech/Qt-4.2.1/lib/libQtSvg.so.4.2.1.debug...
--5349--    object doesn't have a symbol table
==5349== Syscall param write(buf) points to uninitialised byte(s)
==5349==    at 0x4C23233: __write_nocancel (in /lib/libpthread-2.4.so)
==5349==    by 0x490129E: _X11TransWrite (in /usr/X11R6/lib/libX11.so.6.2)
==5349==    by 0x48E5C76: (within /usr/X11R6/lib/libX11.so.6.2)
==5349==    by 0x48E5D7A: _XReply (in /usr/X11R6/lib/libX11.so.6.2)
==5349==    by 0x48D2181: XInternAtom (in /usr/X11R6/lib/libX11.so.6.2)
==5349==    by 0x48EE1FD: XSetWMProperties (in /usr/X11R6/lib/libX11.so.6.2)
==5349==    by 0x420743D: QWidgetPrivate::create_sys(unsigned long, bool, 
bool) (qwidget_x11.cpp:603)
==5349==    by 0x41DA2C1: QWidget::create(unsigned long, bool, bool) 
(qwidget.cpp:1058)
==5349==    by 0x41DECD3: QWidget::setVisible(bool) (qwidget.cpp:5040)
==5349==    by 0x80B24BA: QWidget::show() (qwidget.h:417)
==5349==    by 0x80B7AEB: main (main.cpp:60)
==5349==  Address 0x510EA28 is 544 bytes inside a block of size 16,384 alloc'd
==5349==    at 0x402064B: calloc 
(in /usr/lib/valgrind/x86-linux/vgpreload_memcheck.so)
==5349==    by 0x48D5FB6: XOpenDisplay (in /usr/X11R6/lib/libX11.so.6.2)
==5349==    by 0x41F1511: ??? (qapplication_x11.cpp:1450)
==5349==    by 0x419ADC8: QApplicationPrivate::construct(_XDisplay*, unsigned 
long, unsigned long) (qapplication.cpp:660)
==5349==    by 0x419BBB2: QApplication::QApplication(int&, char**, int) 
(qapplication.cpp:573)
==5349==    by 0x80B7803: main (main.cpp:49)
--5349-- Reading syms 
from /usr/local/Trolltech/Qt-4.2.1/plugins/sqldrivers/libqsqlite.so 
(0x5E67000)
--5349-- Reading debug info 
from /usr/local/Trolltech/Qt-4.2.1/plugins/sqldrivers/libqsqlite.so.debug...
--5349--    object doesn't have a symbol table
==5349== 
==5349== Syscall param writev(vector[...]) points to uninitialised byte(s)
==5349==    at 0x4DF2742: do_writev (in /lib/libc-2.4.so)
==5349==    by 0x4DF280A: writev (in /lib/libc-2.4.so)
==5349==    by 0x49016DD: (within /usr/X11R6/lib/libX11.so.6.2)
==5349==    by 0x49012FE: _X11TransWritev (in /usr/X11R6/lib/libX11.so.6.2)
==5349==    by 0x48E5A80: _XSend (in /usr/X11R6/lib/libX11.so.6.2)
==5349==    by 0x48DA677: (within /usr/X11R6/lib/libX11.so.6.2)
==5349==    by 0x48DA84F: XPutImage (in /usr/X11R6/lib/libX11.so.6.2)
==5349==    by 0x423D65A: QPixmap::fromImage(QImage const&, 
QFlags<Qt::ImageConversionFlag>) (qpixmap_x11.cpp:1152)
==5349==    by 0x423A1CC: QPixmap::load(QString const&, char const*, 
QFlags<Qt::ImageConversionFlag>) (qpixmap.cpp:600)
==5349==    by 0x423A6C4: QPixmap::QPixmap(QString const&, char const*, 
QFlags<Qt::ImageConversionFlag>) (qpixmap.cpp:158)
==5349==    by 0x80A547C: mainwindow::createActions() (kf3mainwindow.cpp:501)
==5349==    by 0x80AA3EC: mainwindow::mainwindow(Relay*, QWidget*, 
QFlags<Qt::WindowType>) (kf3mainwindow.cpp:90)
==5349==  Address 0x510E879 is 113 bytes inside a block of size 16,384 alloc'd
==5349==    at 0x402064B: calloc 
(in /usr/lib/valgrind/x86-linux/vgpreload_memcheck.so)
==5349==    by 0x48D5FB6: XOpenDisplay (in /usr/X11R6/lib/libX11.so.6.2)
==5349==    by 0x41F1511: ??? (qapplication_x11.cpp:1450)
==5349==    by 0x419ADC8: QApplicationPrivate::construct(_XDisplay*, unsigned 
long, unsigned long) (qapplication.cpp:660)
==5349==    by 0x419BBB2: QApplication::QApplication(int&, char**, int) 
(qapplication.cpp:573)
==5349==    by 0x80B7803: main (main.cpp:49)
==5349== 
==5349== Conditional jump or move depends on uninitialised value(s)
==5349==    at 0x419F28E: ??? (qglobal.h:817)
==5349==    by 0x419F5A3: QBoxLayout::sizeHint() const (qboxlayout.cpp:452)
==5349==    by 0x41B1B64: ??? (qgridlayout.cpp:50)
==5349==    by 0x41B1F2E: ??? (qgridlayout.cpp:681)
==5349==    by 0x41B234C: QGridLayout::setGeometry(QRect const&) 
(qgridlayout.cpp:1099)
==5349==    by 0x41B84BB: QLayoutPrivate::doResize(QSize const&) 
(qlayout.cpp:475)
==5349==    by 0x41B9167: QLayout::activate() (qlayout.cpp:1032)
==5349==    by 0x41DEA7B: QWidget::setVisible(bool) (qwidget.cpp:5071)
==5349==    by 0x41C62F0: QStackedLayout::setCurrentIndex(int) (qwidget.h:417)
==5349==    by 0x41C66D1: QStackedLayout::insertWidget(int, QWidget*) 
(qstackedlayout.cpp:200)
==5349==    by 0x41C6713: QStackedLayout::addWidget(QWidget*) 
(qstackedlayout.cpp:172)
==5349==    by 0x44AC22C: QStackedWidget::addWidget(QWidget*) 
(qstackedwidget.cpp:151)
--5349-- Reading syms from /usr/X11R6/lib/X11/locale/lib/common/ximcp.so.2 
(0x7FEA000)
--5349--    object doesn't have a symbol table
==5349== 
==5349== Conditional jump or move depends on uninitialised value(s)
==5349==    at 0x419F28E: ??? (qglobal.h:817)
==5349==    by 0x419F543: QBoxLayout::minimumSize() const (qboxlayout.cpp:464)
==5349==    by 0x41B834E: QLayout::totalMinimumSize() const (qlayout.cpp:611)
==5349==    by 0x41CF968: QWidget::minimumSizeHint() const (qwidget.cpp:5471)
==5349==    by 0x445E652: QGroupBox::minimumSizeHint() const 
(qgroupbox.cpp:474)
==5349==    by 0x41BA3CA: qSmartMinSize(QWidgetItem const*) 
(qlayoutengine.cpp:290)
==5349==    by 0x41BC66E: QWidgetItem::minimumSize() const 
(qlayoutitem.cpp:517)
==5349==    by 0x419ECFA: ??? (qboxlayout.cpp:162)
==5349==    by 0x419F543: QBoxLayout::minimumSize() const (qboxlayout.cpp:464)
==5349==    by 0x41B834E: QLayout::totalMinimumSize() const (qlayout.cpp:611)
==5349==    by 0x41CF968: QWidget::minimumSizeHint() const (qwidget.cpp:5471)
==5349==    by 0x41BA3CA: qSmartMinSize(QWidgetItem const*) 
(qlayoutengine.cpp:290)
==5349== 
==5349== Conditional jump or move depends on uninitialised value(s)
==5349==    at 0x419F313: ??? (qglobal.h:815)
==5349==    by 0x419F543: QBoxLayout::minimumSize() const (qboxlayout.cpp:464)
==5349==    by 0x41B834E: QLayout::totalMinimumSize() const (qlayout.cpp:611)
==5349==    by 0x41CF968: QWidget::minimumSizeHint() const (qwidget.cpp:5471)
==5349==    by 0x445E652: QGroupBox::minimumSizeHint() const 
(qgroupbox.cpp:474)
==5349==    by 0x41BA3CA: qSmartMinSize(QWidgetItem const*) 
(qlayoutengine.cpp:290)
==5349==    by 0x41BC66E: QWidgetItem::minimumSize() const 
(qlayoutitem.cpp:517)
==5349==    by 0x419ECFA: ??? (qboxlayout.cpp:162)
==5349==    by 0x419F543: QBoxLayout::minimumSize() const (qboxlayout.cpp:464)
==5349==    by 0x41B834E: QLayout::totalMinimumSize() const (qlayout.cpp:611)
==5349==    by 0x41CF968: QWidget::minimumSizeHint() const (qwidget.cpp:5471)
==5349==    by 0x41BA3CA: qSmartMinSize(QWidgetItem const*) 
(qlayoutengine.cpp:290)
==5349== 
==5349== Syscall param write(buf) points to uninitialised byte(s)
==5349==    at 0x4C2325B: (within /lib/libpthread-2.4.so)
==5349==    by 0x490129E: _X11TransWrite (in /usr/X11R6/lib/libX11.so.6.2)
==5349==    by 0x48E5C76: (within /usr/X11R6/lib/libX11.so.6.2)
==5349==    by 0x48E5D7A: _XReply (in /usr/X11R6/lib/libX11.so.6.2)
==5349==    by 0x48CE385: XGetWindowProperty (in /usr/X11R6/lib/libX11.so.6.2)
==5349==    by 0x48CD806: XGetWMHints (in /usr/X11R6/lib/libX11.so.6.2)
==5349==    by 0x420498B: QWidgetPrivate::setWindowIcon_sys(bool) 
(qwidget_x11.cpp:1071)
==5349==    by 0x41DA5E2: QWidget::create(unsigned long, bool, bool) 
(qwidget.cpp:1089)
==5349==    by 0x41DECD3: QWidget::setVisible(bool) (qwidget.cpp:5040)
==5349==    by 0x450327E: QDialog::setVisible(bool) (qdialog.cpp:616)
==5349==    by 0x45021BD: QDialog::exec() (qwidget.h:417)
==5349==    by 0x451E423: ??? (qmessagebox.cpp:1202)
==5349==  Address 0x510E890 is 136 bytes inside a block of size 16,384 alloc'd
==5349==    at 0x402064B: calloc 
(in /usr/lib/valgrind/x86-linux/vgpreload_memcheck.so)
==5349==    by 0x48D5FB6: XOpenDisplay (in /usr/X11R6/lib/libX11.so.6.2)
==5349==    by 0x41F1511: ??? (qapplication_x11.cpp:1450)
==5349==    by 0x419ADC8: QApplicationPrivate::construct(_XDisplay*, unsigned 
long, unsigned long) (qapplication.cpp:660)
==5349==    by 0x419BBB2: QApplication::QApplication(int&, char**, int) 
(qapplication.cpp:573)
==5349==    by 0x80B7803: main (main.cpp:49)
==5349== 
==5349== Conditional jump or move depends on uninitialised value(s)
==5349==    at 0x425FE77: ??? (qpainter.cpp:329)
==5349==    by 0x4264202: QPainter::begin(QPaintDevice*) (qpainter.cpp:1345)
==5349==    by 0x426667D: QPainter::QPainter(QPaintDevice*) 
(qpainter.cpp:1022)
==5349==    by 0x4461E35: QLabel::paintEvent(QPaintEvent*) (qlabel.cpp:887)
==5349==    by 0x41DC2C5: QWidget::event(QEvent*) (qwidget.cpp:5707)
==5349==    by 0x445C353: QFrame::event(QEvent*) (qframe.cpp:633)
==5349==    by 0x446121C: QLabel::event(QEvent*) (qlabel.cpp:878)
==5349==    by 0x4193C3F: QApplicationPrivate::notify_helper(QObject*, 
QEvent*) (qapplication.cpp:3435)
==5349==    by 0x4196315: QApplication::notify(QObject*, QEvent*) 
(qapplication.cpp:3376)
==5349==    by 0x41E3A6D: ??? (qcoreapplication.h:186)
==5349==    by 0x42C4DEB: QWidgetPrivate::drawWidget(QPaintDevice*, QRegion 
const&, QPoint const&, int) (qbackingstore.cpp:758)
==5349==    by 0x42C544F: ??? (qbackingstore.cpp:681)




--
 [ signature omitted ]