PDA

View Full Version : memory leak



mattia
8th January 2008, 15:08
Hello, i'trying to understund why running my app with


valgrind --tool=memcheck --leak-check=yes -v /my/app

i get a sort of memory leak

132 (4 direct, 128 indirect) bytes in 1 blocks are definitely lost in loss record 20 of 163
up here it just a little piece ....
I'm using the "direct approach", what should i do to prevent it?
It looks like when i call a function into my class in this way

parent_object->myFunc()
i earn a leak....:(

----------------- edit -----------------
to be more accurate my leak summury:

==3325== LEAK SUMMARY:
==3325== definitely lost: 708 bytes in 77 blocks.
==3325== indirectly lost: 22729 bytes in 420 blocks.
==3325== possibly lost: 0 bytes in 0 blocks.
==3325== still reachable: 728510 bytes in 26553 blocks.
==3325== suppressed: 0 bytes in 0 blocks.
==3325== Reachable blocks (those to which a pointer was found) are not shown.
==3325== To see them, rerun with: --show-reachable=yes
--3325-- TT/TC: 0 tc sectors discarded.
--3325-- 180208 tt_fast misses.
--3325-- translate: new 89667 (1628736 -> 24489134; ratio 150:10)
--3325-- discard 190 (2620 -> 35740; ratio 136:10).
--3325-- chainings: 71514 chainings, 0 unchainings.
--3325-- dispatch: 98933412 jumps (bb entries); of them 16549827 (16%) unchained.
--3325-- 1979/607625 major/minor sched events.
--3325-- reg-alloc: 15989 t-req-spill, 4351425+95101 orig+spill uis,
--3325-- 484044 total-reg-rank
--3325-- sanity: 1980 cheap, 80 expensive checks.
--3325-- ccalls: 547959 C calls, 54% saves+restores avoided (1744510 bytes)
--3325-- 726410 args, avg 0.90 setup instrs each (138758 bytes)
--3325-- 0% clear the stack (1643130 bytes)
--3325-- 156831 retvals, 34% of reg-reg movs avoided (103722 bytes)

jacek
8th January 2008, 18:35
It looks like when i call a function into my class in this way

parent_object->myFunc()
i earn a leak....:(
Then most likely myFunc() leaks. Do you create any objects using new operator inside it?

mattia
9th January 2008, 09:17
yes i do, for example


void main()
{
...
funz();
funz1();
...
}
void funz()
{
...
for ( int i = 0 ; i < list.size() ; i++ )
{
myTestObject * testObject;

testObject = new ( myTestObject , this );

temptwmConfigPool->doSomeThing( );


myObjectList.append ( testObject );

delete testObject;
}
...
}

if i skip the delete statement it's ok otherwise i get a segmentation fault after it when i call the next function "funz1()", but funz1() does not use the object deleted...
thx

marcel
9th January 2008, 11:05
Do you use myObjectList in other functions?
If so, don't delete testObject in funz(), instead iterate over myObjectList when finished with it and delete each object.

This could explain your mem leaks and the crash when trying to delete testObject.

Regards

mattia
9th January 2008, 12:00
the crash is triggered cos i try to use an object deleted...i more checked and it was a my mystake. ;)
But what should i do if i want to avoid this:


void main::setUp( QTreeWidget * thetwmTreeWidget )
{
QList<QTreeWidgetItem *> items;

for ( int i = 0; i < list.size() ; i++ )
{
QTreeWidgetItem * tempQTreeWidgetItem = new QTreeWidgetItem ();

tempQTreeWidgetItem->setText ( 0 , list.at(1) );

items.append ( tempQTreeWidgetItem );
}
thetwmTreeWidget->setColumnCount (1);
thetwmTreeWidget->insertTopLevelItems (0, items);
}

When i create

QTreeWidgetItem * tempQTreeWidgetItem = new QTreeWidgetItem ();

don't i earn a memory leak?
But i can't delete tempQTreeWidgetItem at the end of my application cos i have a scope problem, i can't see it, tempQTreeWidgetItem is just declared in setUp().
I can't delete it at the setUp() end cos thetwmTreeWidget is used in my GUI.
Is it right?

jacek
9th January 2008, 14:58
If you want to delete an object you no longer use, you have to do that before it goes out of scope, because you won't be able to reach it later.

In this case you don't have to delete the object that tempQTreeWidgeItem points to, because you add it to thetwmTreeWidget, which is responsible for deleting it.

mattia
9th January 2008, 16:19
If you want to delete an object you no longer use, you have to do that before it goes out of scope, because you won't be able to reach it later.

In this case you don't have to delete the object that tempQTreeWidgeItem points to, because you add it to thetwmTreeWidget, which is responsible for deleting it.
Thanks so much for the explanetion.
Get back at my memory leak cos i'm not able to understand where i'm getting wrong.
This is a little piece of valgrind command report:


==16797== 2848 (16 direct, 2832 indirect) bytes in 4 blocks are definitely lost in loss record 75 of 144
==16797== at 0x1B90939A: operator new(unsigned) (vg_replace_malloc.c:132)
==16797== by 0x818DE38: twmConfigObject::getPoolIconTooltip(int, QString) (twmConfig.cpp:4968)
==16797== by 0x81ADCB9: twmConfigObject::setupPoolsGetTreeView(QTreeWidget *, bool) (twmConfig.cpp:1210)
==16797== by 0x80BA4D0: twmMainWindow::setupPools(bool) (twmMainWindow.cpp:1387)
==16797== by 0x812DE02: twmMainWindow::twmMainWindow(QWidget*) (twmMainWindow.cpp:54)
==16797== by 0x80A0317: main (trm.cpp:62)

I think that the problem is in my twmConfigObject::getPoolIconTooltip(int, QString) method, and down here the method's code:


QString twmConfigObject::getPoolIconTooltip ( int theStatus , QString poolName )
{
QString difference;
countNotSync( TWMACTUALMODE__POOLS , false , & difference );

switch ( theStatus )
{
case POOLSTATUS__UNDEF:

if ( ! difference.isEmpty() && difference != 0)
{
return ( QString ( tr ( "Pool %1 status is: Undefined - %2 difference" ).arg ( poolName ).arg ( difference ) ) );
}
else
{
return ( QString ( tr ( "Pool %1 status is: Undefined" ).arg ( poolName ) ) );
}
break;

case POOLSTATUS__INCOMPLETESHARE:

if ( ! difference.isEmpty() && difference != 0)
{
return ( QString ( tr ( "Pool %1 status is: Incomplete share - %2 difference" ).arg ( poolName ).arg ( difference ) ) );
}
else
{
return ( QString ( tr ( "Pool %1 status is: Incomplete share" ).arg (poolName) ) );
}
break;

case POOLSTATUS__SHARED:

if ( ! difference.isEmpty() && difference != 0)
{
return ( QString ( tr ( "Pool %1 status is: Shared - %2 difference" ).arg ( poolName ).arg ( difference ) ) );
}
else
{
return ( QString ( tr ( "Pool %1 status is: Shared" ).arg (poolName) ) );
}
break;

default:

return ( QString ( tr ( "Terminal %1 status is: Undefined" ).arg (poolName) ) );
break;
}
}

any hint?

jacek
9th January 2008, 23:03
Is new operator used in countNotSync()?

mattia
10th January 2008, 21:18
No, i don't use any new operator in that function, but i call some other functions and there are not new statement into them.
:(

jacek
10th January 2008, 21:29
Does the leak disappear, if you comment out all of the code and add "return QString();" instead?

mattia
11th January 2008, 16:42
i have a trouble to read the leak summary...


#
==3325== definitely lost: 708 bytes in 77 blocks.
#
==3325== indirectly lost: 22729 bytes in 420 blocks.
#
==3325== possibly lost: 0 bytes in 0 blocks.
#
==3325== still reachable: 728510 bytes in 26553 blocks. <-- have i lost them(728510bytes)?

jacek
11th January 2008, 19:17
have i lost them(728510bytes)?
No, there's still some way to reach that data. For example Qt might store pointers somewhere inside itself.

Whether that's a leak or not depends on whether this amount rises with time or not. For example if you have a loop where you create temporary QObjects, give them a parent and forget to delete them. You will get a leak, but the data is "reachable" all the time through the parent. On other hand you might create a single array using new operator and as long as there's only one such array you don't have a leak, even if you never free the memory it occupies.

mattia
11th January 2008, 19:44
ok, thx so much but is it a my business to delete it?
from that you said up here it is not a my business to delete it, does Qt do it?

jacek
12th January 2008, 19:25
ok, thx so much but is it a my business to delete it?
Only if you are the owner of that memory. Although there is nothing wrong in having unallocated, but reachable memory at program exit.

mattia
15th January 2008, 07:41
I think i get the big problem, try to check please:



==26261== 4136 (2204 direct, 1932 indirect) bytes in 1 blocks are definitely lost in loss record 124 of 139
==26261== at 0x1B90939A: operator new(unsigned) (vg_replace_malloc.c:132)
==26261== by 0x809FC82: main (trm.cpp:62)


trm.cpp


int main ( int argc, char *argv[] )
{
QApplication app ( argc, argv );
...
...
// creating splash object
QPixmap pixmap ( ":/trm/images/SplashScreen.png" );
QSplashScreen * splash = new QSplashScreen ( pixmap );
splash->show();
splash->showMessage ( QObject::tr ("Loading settings..." ) , Qt::AlignRight | Qt::AlignBottom , Qt::black );

// creating main window
twmMainWindow *mytwmMainWindow = new twmMainWindow(); // <-- trm.cpp:62
mytwmMainWindow->show();

// closing and destroing splash screen
splash->finish ( mytwmMainWindow );
delete splash;

// run the main loop!
return app.exec();
}


Where hould i delete the statement in trm.cpp:62?
I have to put it in my trm.h and in trm.cpp i have just to do
mytwmMainWindow = new twmMainWindow();
and destroy it at the end?
Thx

jpn
15th January 2008, 10:02
Just allocate it on the stack:


twmMainWindow mytwmMainWindow(); // <-- trm.cpp:62
mytwmMainWindow.show();

or alternatively set Qt::WA_CloseOnDelete attribute:

twmMainWindow *mytwmMainWindow = new twmMainWindow(); // <-- trm.cpp:62
mytwmMainWindow->setAttribute(Qt::WA_DeleteOnClose);
mytwmMainWindow->show();

mattia
15th January 2008, 10:55
Just allocate it on the stack:


twmMainWindow mytwmMainWindow(); // <-- trm.cpp:62
mytwmMainWindow.show();


In this way i got this error

error: request for member ‘show’ in ‘mytwmMainWindow’, which is of non-class type ‘twmMainWindow (

Just allocate it on the stack:
or alternatively set Qt::WA_CloseOnDelete attribute:

twmMainWindow *mytwmMainWindow = new twmMainWindow(); // <-- trm.cpp:62
mytwmMainWindow->setAttribute(Qt::WA_DeleteOnClose);
mytwmMainWindow->show();


In this way i'm able to run my app but nothing change...
thx

jpn
15th January 2008, 11:26
In this way i got this error

error: request for member ‘show’ in ‘mytwmMainWindow’, which is of non-class type ‘twmMainWindow (

I didn't notice that class and variable names were exactly the same. So rename the variable name to be something different than what the class name is. For example:


twmMainWindow mainWindow; // <-- trm.cpp:62
mainWindow.show();

mattia
16th January 2008, 10:22
thanks so much! I learned a lot of cool stuff about memory leak and i fixed my problem. ;)