PDA

View Full Version : When I use Listview with icons its causing memory leak



GuusDavidson
28th March 2011, 01:36
I am using QT 4.6
Nokia N8 (Symbian)

I am having a bit of a memory issue using the SlidingStackedWidget to hold nine list view widgets, that each display approx 20 items.

To try and conserve memory I am loading only the images for the currently displayed widget.
I am controlling the loading/unloading by capturing the widget event for show and hide, and using this to repolulate my model for the list view.

I am also using the PixmapCache as a mechanism to cache images that I have loaded, I have set my cache size to 2048k

My code for loading the pixmap, and populating / clearing the list model is listed below.

When I run this on the Nokia N8, and transition between widgets, I very quickly run out of memory, when loading images.

From my observations (I have included the code I use to trace memory usage) there is a mismatch between the amount of data allocated between
the populateModel and clearModel methods. When I transition to a new screen the memory allways increases, and when I clear the model, it never seems to remove enough memory.

1. I am concerned that I am misusing the PixmapCache, the help states,
"QPixmaps are automatically added to the QPixmapCache when loaded from a file; the key used is internal and can not be acquired."
Should I be bothering to cache Pixmaps as I load them, as it would appear the system is already doing this for me?

2. Does the models appendRow method take ownership of the item data?
do I need to clear the model row by row, prior to calling clear?

3. can anyone point out where I am leaking memory?

thanks in advance

Guus Davidson



#ifdef Q_OS_SYMBIAN
TInt mem, size, limit;
User::Heap().AllocSize(mem);
size = User::Heap().Size();
limit = User::Heap().MaxLength();

qDebug() << QString("Heap Mem : %1").arg(mem);
qDebug() << QString("Heap Size : %1").arg(size);
qDebug() << QString("Heap Limit : %1").arg(limit);
#endif







QPixmap FileImageCache::getPixmap(const QString& key)
{
QPixmap pm;
if (!QPixmapCache::find(key, &pm))
{
pm.load(diskCacheDirectory + "//" +key);
bool result = QPixmapCache::insert(key, pm);
return pm;
}






void DisplayWidget::populateModel()
{
if(iModelCleared == true)
{
BaseDisplayWidget::populateModel();

QStandardItemModel* model = dynamic_cast<QStandardItemModel*>(iListView->model());
int defaultIconCount = 0;
if(model != 0 && iAppStoreChannel != 0)
{
QList<AppstoreItem*> items = iAppStoreChannel->getItems();

int count = items.count();
AppstoreItem* currentItem = 0;

for(int i = 0; i < count ; i++)
{
bool defaultIconUsed = true;
currentItem = items.at(i);

QString url = currentItem->getIconUrl();
QIcon icon_image;
if(url.length() > 0)
{
QString key = iImageCache->getKeyForImageLocation(url);
if(iImageCache->containsKey(key) == true)
{
QPixmap pixmap= iImageCache->getPixmap(key);

if(!pixmap.isNull())
{
defaultIconUsed = false;
icon_image.addPixmap(pixmap);
}
else
{
defaultIconCount ++;
}
}
}

isdefaultIcon.append(defaultIconUsed);
QStandardItem* item = new QStandardItem();

item->setData(currentItem ->getHeadline(),ChannelListViewDelegate::headerTextR ole);
item->setData(currentItem ->getDescription(),ChannelListViewDelegate::subHeade rTextrole);
if(icon_image.isNull())
{
item->setData(*icon_default,ChannelListViewDelegate::Ico nRole);
}
else
{
item->setData(icon_image,ChannelListViewDelegate::IconRo le);
}
model->appendRow(item);
}
}
}
}






void DisplayWidget::clearModel()
{
if(iModelCleared == false)
{
QStandardItemModel* ptr = dynamic_cast<QStandardItemModel*>(iListView->model());
if(ptr != 0)
{
ptr->clear();
iModelCleared = true;
delete ptr;
}
}
}

high_flyer
28th March 2011, 09:45
Where do you clear (and delete the items) of a list in AppstoreItems in iAppStoreChannel?:

QList<AppstoreItem*> items = iAppStoreChannel->getItems();

GuusDavidson
28th March 2011, 23:48
Hi, these belong to the AppSotreChannel Class, it owns this data.


Guus

high_flyer
29th March 2011, 09:33
Never the less it must also take cere of deleting it, you have to make sure everywhere in your application that any dynamically allocated memory is also released!

wariola
29th March 2011, 23:08
You can use Insure++ to assist you here:

http://www.parasoft.com/jsp/resources/memory_error_detection