How to solve processCapturedImage slot memory leak?
-
#include <QBuffer> #include <QCoreApplication> #include <QDateTime> #include <QJsonDocument> #include <QJsonObject> #include <QFile> #include <QCameraViewfinder> camera::camera(QObject *parent):QThread(parent) { const QList<QCameraInfo> cameras = QCameraInfo::availableCameras(); for (const QCameraInfo &cameraInfo : cameras)// { qDebug() << cameraInfo.deviceName(); if(CameraV != nullptr) { delete CameraV; CameraV = nullptr; } CameraV = new QCamera(cameraInfo); if(CameraV != nullptr) { CameraImageCapture = new QCameraImageCapture(CameraV); CameraImageCapture->setCaptureDestination(QCameraImageCapture::CaptureToBuffer);//Not File Only To Buffer connect(CameraImageCapture, &QCameraImageCapture::readyForCaptureChanged, this, &camera::CaptureStatusChanged); connect(CameraImageCapture, &QCameraImageCapture::imageCaptured, this, &camera::processCapturedImage); connect(this, SIGNAL(RequestCapture()), this, SLOT(ImageCapture())); CameraV->setCaptureMode(QCamera::CaptureStillImage); CameraV->start(); this->start(); } break; } } void camera::run() { while(true) { //emit ReqCurrentSave(); emit RequestCapture(); //QThread::sleep(1); //QThread::msleep(1); } } void camera::ImageCapture() { if (CameraImageCapture != nullptr && Camera_Available == true) { CameraImageCapture->capture(); } } camera::~camera() { if (CameraImageCapture != nullptr) { delete CameraImageCapture; CameraImageCapture = nullptr; } if (CameraV != nullptr) { CameraV->stop(); delete CameraV; CameraV = nullptr; } } void camera::CaptureStatusChanged(bool ready) { qDebug()<<"Chagned to"<<ready; this->Camera_Available = ready; } void camera::processCapturedImage(int requestId, const QImage& img) { Q_UNUSED(requestId); qDebug() << "Test!"; }
OS : raspberry pi3
RAM : 2GAfter the camera capture is done in the thread, the captured signal is registered(QObject::Connect) in the processCapturedImage slot.
In that slot, we write the image to public QByteArray(Using Buffer).
QByteArray is referenced by another class.My problem is that I am currently experiencing a memory leak over time.
The question is:
- After the slot ends, are the variables created within the slot automatically freed?
- Should variables such as QByteArray, Buffer.Close or Image, declared in slots or passed as arguments, always be returned using delete or delete[]?
- Does using QByteArray.Clear() return resources?
- What is my problem to memory leak? i tried 1month for solve this..
Thank you for read it
-
#include <QBuffer> #include <QCoreApplication> #include <QDateTime> #include <QJsonDocument> #include <QJsonObject> #include <QFile> #include <QCameraViewfinder> camera::camera(QObject *parent):QThread(parent) { const QList<QCameraInfo> cameras = QCameraInfo::availableCameras(); for (const QCameraInfo &cameraInfo : cameras)// { qDebug() << cameraInfo.deviceName(); if(CameraV != nullptr) { delete CameraV; CameraV = nullptr; } CameraV = new QCamera(cameraInfo); if(CameraV != nullptr) { CameraImageCapture = new QCameraImageCapture(CameraV); CameraImageCapture->setCaptureDestination(QCameraImageCapture::CaptureToBuffer);//Not File Only To Buffer connect(CameraImageCapture, &QCameraImageCapture::readyForCaptureChanged, this, &camera::CaptureStatusChanged); connect(CameraImageCapture, &QCameraImageCapture::imageCaptured, this, &camera::processCapturedImage); connect(this, SIGNAL(RequestCapture()), this, SLOT(ImageCapture())); CameraV->setCaptureMode(QCamera::CaptureStillImage); CameraV->start(); this->start(); } break; } } void camera::run() { while(true) { //emit ReqCurrentSave(); emit RequestCapture(); //QThread::sleep(1); //QThread::msleep(1); } } void camera::ImageCapture() { if (CameraImageCapture != nullptr && Camera_Available == true) { CameraImageCapture->capture(); } } camera::~camera() { if (CameraImageCapture != nullptr) { delete CameraImageCapture; CameraImageCapture = nullptr; } if (CameraV != nullptr) { CameraV->stop(); delete CameraV; CameraV = nullptr; } } void camera::CaptureStatusChanged(bool ready) { qDebug()<<"Chagned to"<<ready; this->Camera_Available = ready; } void camera::processCapturedImage(int requestId, const QImage& img) { Q_UNUSED(requestId); qDebug() << "Test!"; }
OS : raspberry pi3
RAM : 2GAfter the camera capture is done in the thread, the captured signal is registered(QObject::Connect) in the processCapturedImage slot.
In that slot, we write the image to public QByteArray(Using Buffer).
QByteArray is referenced by another class.My problem is that I am currently experiencing a memory leak over time.
The question is:
- After the slot ends, are the variables created within the slot automatically freed?
- Should variables such as QByteArray, Buffer.Close or Image, declared in slots or passed as arguments, always be returned using delete or delete[]?
- Does using QByteArray.Clear() return resources?
- What is my problem to memory leak? i tried 1month for solve this..
Thank you for read it
@1stetcgoldmedal said in How to solve processCapturedImage slot memory leak?:
After the slot ends, are the variables created within the slot automatically freed?
If those were allocated on the stack then yes, else you have to free the memory.
I don't understand your code. Why do you have an endless loop where you're constantly emitting a signal?!
Your code also does not show how you actually handle the captured image... -
@1stetcgoldmedal said in How to solve processCapturedImage slot memory leak?:
After the slot ends, are the variables created within the slot automatically freed?
If those were allocated on the stack then yes, else you have to free the memory.
I don't understand your code. Why do you have an endless loop where you're constantly emitting a signal?!
Your code also does not show how you actually handle the captured image... -
@1stetcgoldmedal said in How to solve processCapturedImage slot memory leak?:
After the slot ends, are the variables created within the slot automatically freed?
If those were allocated on the stack then yes, else you have to free the memory.
I don't understand your code. Why do you have an endless loop where you're constantly emitting a signal?!
Your code also does not show how you actually handle the captured image...void camera::processCapturedImage(int requestId, const QImage& img) { Q_UNUSED(requestId); try { if (img.isNull() == false) { Image.clear(); QBuffer buffer(&Image); buffer.open(QIODevice::WriteOnly); img.save(&buffer, "jpg"); buffer.close(); Image = qCompress(Image).toBase64(); id = QDateTime::currentDateTime().toMSecsSinceEpoch(); } else { qDebug()<<"Image is null."; } } catch(std::exception& e) { qDebug() << Q_FUNC_INFO << e.what(); } }
here is image processing method..
i think..there is no problem. -
@jsulm the OP is also playing a dangerous game of chicken and who's memory is it.
I would bet that the RequestCapture signal that if flooding the event system is the presumed "memory leak"
@J-Hilk
Chaged Code :#include "camera.h" #include <QBuffer> #include <QCoreApplication> #include <QDateTime> #include <QJsonDocument> #include <QJsonObject> #include <QFile> #include <QCameraViewfinder> camera::camera(QObject *parent):QThread(parent) { const QList<QCameraInfo> cameras = QCameraInfo::availableCameras(); for (const QCameraInfo &cameraInfo : cameras)// { qDebug() << cameraInfo.deviceName(); if(CameraV != nullptr) { delete CameraV; CameraV = nullptr; } CameraV = new QCamera(cameraInfo); if(CameraV != nullptr) { CameraImageCapture = new QCameraImageCapture(CameraV); CameraImageCapture->setCaptureDestination(QCameraImageCapture::CaptureToBuffer);//Not File Only To Buffer connect(CameraImageCapture, &QCameraImageCapture::readyForCaptureChanged, this, &camera::CaptureStatusChanged); connect(CameraImageCapture, &QCameraImageCapture::imageCaptured, this, &camera::processCapturedImage); connect(this, SIGNAL(RequestCapture()), this, SLOT(ImageCapture())); CameraV->setCaptureMode(QCamera::CaptureStillImage); CameraV->start(); this->start(); } break; } } void camera::run() { while(true) { emit ReqCurrentSave(); emit RequestCapture(); QThread::sleep(1); //QThread::msleep(1); } } void camera::ImageCapture() { if (CameraImageCapture != nullptr && Camera_Available == true) { CameraImageCapture->cancelCapture();//CHANGED HERE! CameraImageCapture->capture(); } } camera::~camera() { if (CameraImageCapture != nullptr) { delete CameraImageCapture; CameraImageCapture = nullptr; } if (CameraV != nullptr) { CameraV->stop(); delete CameraV; CameraV = nullptr; } } void camera::CaptureStatusChanged(bool ready) { qDebug()<<"Chagned to"<<ready; this->Camera_Available = ready; } void camera::processCapturedImage(int requestId, const QImage& img) { Q_UNUSED(requestId); try { if (img.isNull() == false) { Image.clear(); QBuffer buffer(&Image); buffer.open(QIODevice::WriteOnly); img.save(&buffer, "jpg"); buffer.close(); Image = qCompress(Image).toBase64(); id = QDateTime::currentDateTime().toMSecsSinceEpoch(); } else { qDebug()<<"Image is null."; } } catch(std::exception& e) { qDebug() << Q_FUNC_INFO << e.what(); } }
Edited as above.
If the image capture signal is faster than the image processing,
As the images to be processed pile up, the memory will gradually increase.
So, I put the command to cancel the capture as above.
However, it seems that the memory usage is slowly increasing.
Of course, my code doesn't just have a camera class.
There is also a class that reads values from serial ports.
It exists as a code that transmits the value received from the image and serial port to the tcp server.
Most of these also use threads, and at the same time use events.
I tried tools like valgrind to fix this leak, but it didn't work.
What could be the problem?
Would it be better to create and use a bool type temporary variable to capture after the capture process is completed?
sorry for bad english -
@J-Hilk
Chaged Code :#include "camera.h" #include <QBuffer> #include <QCoreApplication> #include <QDateTime> #include <QJsonDocument> #include <QJsonObject> #include <QFile> #include <QCameraViewfinder> camera::camera(QObject *parent):QThread(parent) { const QList<QCameraInfo> cameras = QCameraInfo::availableCameras(); for (const QCameraInfo &cameraInfo : cameras)// { qDebug() << cameraInfo.deviceName(); if(CameraV != nullptr) { delete CameraV; CameraV = nullptr; } CameraV = new QCamera(cameraInfo); if(CameraV != nullptr) { CameraImageCapture = new QCameraImageCapture(CameraV); CameraImageCapture->setCaptureDestination(QCameraImageCapture::CaptureToBuffer);//Not File Only To Buffer connect(CameraImageCapture, &QCameraImageCapture::readyForCaptureChanged, this, &camera::CaptureStatusChanged); connect(CameraImageCapture, &QCameraImageCapture::imageCaptured, this, &camera::processCapturedImage); connect(this, SIGNAL(RequestCapture()), this, SLOT(ImageCapture())); CameraV->setCaptureMode(QCamera::CaptureStillImage); CameraV->start(); this->start(); } break; } } void camera::run() { while(true) { emit ReqCurrentSave(); emit RequestCapture(); QThread::sleep(1); //QThread::msleep(1); } } void camera::ImageCapture() { if (CameraImageCapture != nullptr && Camera_Available == true) { CameraImageCapture->cancelCapture();//CHANGED HERE! CameraImageCapture->capture(); } } camera::~camera() { if (CameraImageCapture != nullptr) { delete CameraImageCapture; CameraImageCapture = nullptr; } if (CameraV != nullptr) { CameraV->stop(); delete CameraV; CameraV = nullptr; } } void camera::CaptureStatusChanged(bool ready) { qDebug()<<"Chagned to"<<ready; this->Camera_Available = ready; } void camera::processCapturedImage(int requestId, const QImage& img) { Q_UNUSED(requestId); try { if (img.isNull() == false) { Image.clear(); QBuffer buffer(&Image); buffer.open(QIODevice::WriteOnly); img.save(&buffer, "jpg"); buffer.close(); Image = qCompress(Image).toBase64(); id = QDateTime::currentDateTime().toMSecsSinceEpoch(); } else { qDebug()<<"Image is null."; } } catch(std::exception& e) { qDebug() << Q_FUNC_INFO << e.what(); } }
Edited as above.
If the image capture signal is faster than the image processing,
As the images to be processed pile up, the memory will gradually increase.
So, I put the command to cancel the capture as above.
However, it seems that the memory usage is slowly increasing.
Of course, my code doesn't just have a camera class.
There is also a class that reads values from serial ports.
It exists as a code that transmits the value received from the image and serial port to the tcp server.
Most of these also use threads, and at the same time use events.
I tried tools like valgrind to fix this leak, but it didn't work.
What could be the problem?
Would it be better to create and use a bool type temporary variable to capture after the capture process is completed?
sorry for bad english@1stetcgoldmedal Maybe I missed it, but is the camera destructor ~camera() ever called?
-
@1stetcgoldmedal Maybe I missed it, but is the camera destructor ~camera() ever called?
@BwvB said in How to solve processCapturedImage slot memory leak?:
Maybe I missed it, but is the camera destructor ~camera() ever called?
Not in your code you showed us but hopefully at the place where you created it before.
-
@1stetcgoldmedal Maybe I missed it, but is the camera destructor ~camera() ever called?
@BwvB No. it's never called
-
@1stetcgoldmedal said in How to solve processCapturedImage slot memory leak?:
After the slot ends, are the variables created within the slot automatically freed?
If those were allocated on the stack then yes, else you have to free the memory.
I don't understand your code. Why do you have an endless loop where you're constantly emitting a signal?!
Your code also does not show how you actually handle the captured image...@jsulm I don't understand your code. Why do you have an endless loop where you're constantly emitting a signal?!
i'd like to save image(public QByteArray variable) on realtime.
and i send image to server from public attribute (QByteArray Image) in camera classconnect(CameraImageCapture, &QCameraImageCapture::imageAvailable, [=] (int id, QVideoFrame v ) { if (v.isValid()) { if(v.map(QAbstractVideoBuffer::ReadOnly)) { Image.clear(); QBuffer buffer(&Image); buffer.open(QIODevice::WriteOnly); v.image().save(&buffer, "jpg"); buffer.close(); Image = qCompress(Image).toBase64(); this->id = QDateTime::currentDateTime().toMSecsSinceEpoch(); v.unmap(); } } });
here is my updated code.
imageCaptured Signal -> imageAvailable Signal