PDA

View Full Version : Displaying pixmaps and memory leak ??



tonytony
28th June 2010, 13:25
Hi,

I'm fairly new to qt, I'm using qt creator on both linux and mac and the same code is causing the same problem on both platforms. Anyway I'm trying to display an image from a camera and while it is displaying it's also causing a memory leak which over time eventually crashes the computer. I've had a look online but can't seem to find anything on this. If I comment out the code that displays the image then the rest of the program works fine with no memory leak and no crash.



void MainWindow::display_image()
{
if(moving > 0) moving --;
get_camera(ui->horizontalSlider_scan_size->value(), ui->horizontalSlider_colour_threshold->value());

//--------------------------------------------------------------draw camera views
if(ui->checkBox_vis->isChecked()) {
ui->graphicsView_left_cam->setScene(left_cam_view);
ui->graphicsView_left_cam->show();
ui->graphicsView_left_cam->setSceneRect(0,0,image_width,image_height);
limage = QImage(image_width, image_height, QImage::Format_ARGB32);

#pragma omp parallel for
for(int x=0; x<image_width; x++) {
for(int y=0; y<image_height; y++) {
QRgb lvalue = qRgba(left_image[x][y][0], left_image[x][y][1], left_image[x][y][2], 255);
limage.setPixel(x,y,lvalue);
}
}

lpixmap = QPixmap::fromImage(limage);
left_cam_view->addPixmap(lpixmap);
}


So whats going on here is... I have an image which is stored in a matrix x by y by 3 (r,g,b) so I set the value of a pixel and then set that pixel in a Qimage.

So the user presses a button to start things off and that causes a hidden button to repeat which calls this function...



void MainWindow::on_pushButton_start_clicked()
{
ui->refresh->setDown(true);
ui->refresh->setAutoRepeat(true);
ui->refresh->setAutoRepeatInterval(50);
}

void MainWindow::on_refresh_clicked()
{
display_image();
}



Thats it, so why do I get the memory leak? what have I missed or misunderstood about this?

Cheers

Vit Stepanek
28th June 2010, 14:09
Can you show the implementation of left_cam_view->addPixmap(lpixmap);?
I see no dynamic allocations here, are you sure that the crash is caused by a memory leaks?

tonytony
28th June 2010, 14:51
Hmm I'm not sure what you mean by the implementation of left_cam_view->addPixmap(lpixmap);
This is part of qt creator. The initializations are...

QGraphicsScene *left_cam_view;
QImage limage;
QPixmap lpixmap;

As for the memory leak, if ui->checkBox_vis->isChecked() is not checked so the first function doesn't do the drawing bit then the program memory is constant and it can run a long time with no problem.
When it is checked so the drawing function is used then the memory usage fluctuates and generally goes up, but over time the overall memory in use by programs goes up hugely and keeps going up until first the program slows down and finally the computer freezes. Quitting the program and the shell from which it is launched does not free this memory. In fact from the system monitor it shows that while GiB's are in use by programs, the memory in use by processes is not that much.

From all this it would seem that the problem is due to this small bit of code (as without it there is no problem).

MorrisLiang
28th June 2010, 15:19
Are you sure calling QGraphicsScene::addPixmap() will clear the previous one?
The Qt Assistant doesn't say anything about this, but if it doesn't clear the previous QPixmap, it definitely is a leak.

tonytony
28th June 2010, 15:28
Are you sure calling QGraphicsScene::addPixmap() will clear the previous one?
The Qt Assistant doesn't say anything about this, but if it doesn't clear the previous QPixmap, it definitely is a leak.

This is pretty much what I thought might be the problem but I have no idea how to fix it...

tonytony
28th June 2010, 17:43
Ok so clearly this is not the way to do things...

I'm struggling to work out how to draw a QImage or QPixmap onto the GUI though. I can find loads of examples but they are not QT creator applications using the QGraphicsView object. I can set the scene etc but how to set it to use my image without using something like addPixmap which doesn't remove the old pixmap?

MorrisLiang
29th June 2010, 07:01
Basically, calling QGraphicsScene::addPixmap() will return a QGraphicsPixmapItem. So all you have to do is to hold the QGraphicsPixmapItem pointer when adding a pixmap. When adding another pixmap, delete the previous QGraphicsPixmapItem first.



void MainWindow::display_image()
{
...
lpixmap = QPixmap::fromImage(limage);
if(myPixmapItem)
delete myPixmapItem;
myPixmapItem= left_cam_view->addPixmap(lpixmap);
}


the myPixmapItem is a member of MainWindow, a pointer to QGraphicsPixmapItem. Remember to set it to 0 when constructing a MainWindow Object.



Another way is,


void MainWindow::init()
{
...
myPixmapItem = new QGraphicsPixmapItem();
left_cam_view->addItem(myPixmapItem);
...
}

void MainWindow::display_image()
{
...
QPixmap lpixmap = QPixmap::fromImage(image);
myPixmapItem->setPixmap(lpixmap);
...
}

In this way, you will only have a QGraphicsPixmapItem and no more creating and deleting. This one would be better solution. I'm sure calling QGraphicsPixmapItem::setPixmap() will clear the previous QPixmap.

Some other things are that you're creating a QImage and a QPixmap in the stack every time the display_image() is called. This will cause constructing and destructing them. I think it's better to make them members of the MainWindow. And then you don't have to construct and destruct them. It shouldn't take too much memory, since QPixmap is implicit sharing.

tonytony
29th June 2010, 14:12
Ok so before I saw the last post I discovered that clearing the scene fixed the problem, but it looks like the last post gives a more elegant solution. Thanks for you help with this!