我正在尝试加速我的(qt c ++ opencv)程序,该程序应该计算我的照片中的颜色数量,以便将来过滤。 单线程方法没有泄漏,但速度非常慢。
通过添加8个线程,我已经将此过程加速了5倍。
当我将程序切换到多线程时,问题就开始了。
存在巨大的内存泄漏! http://snag.gy/cHRrS.jpg
遵循此建议(https://stackoverflow.com/a/12859444) 我阻止了继承QThread并实现run()。
这是一个for循环,用于计算每个移位1个像素的新图像中的每个像素:
ColorCounterController *cntrl[arrSize];
for (int i = 0; i < box; i++)//x
{
for (int j = 0; j < box; ++j)//y
{
cv::Mat res=process(image,i,j);
//Using 1 core
//colors=ColorDetectController::getInstance()->colorsCount(res);
//Using all 8 cores
cntrl[cnt2%arrSize]= new ColorCounterController(res,this);
++cnt2;
}
++cnt;
emit setStatusProgressSignal((int)(cnt/amnt*100));
}
delete[] *cntrl;
评论:
当使用1核(上面的代码)时,我有单例来运行colorsCount(res)函数。 在8核的情况下,我使用几乎相同的功能,但从ColorCounterController调用。
class ColorCounterController : public QObject{
Q_OBJECT
private:
QThread thread;
ColorCounter *colorCntr;
Pixalate *pixelate;
private slots:
void freecolorCntr(){
delete colorCntr;
}
public:
ColorCounterController(const cv::Mat &image,Pixalate *pxobj) {
colorCntr= new ColorCounter();
colorCntr->setimageThread(image);
colorCntr->moveToThread(&thread);
connect(&thread, SIGNAL(started()), colorCntr, SLOT(colorsCountThread()));
connect(colorCntr, SIGNAL(finished()), &thread, SLOT(quit()));
connect(colorCntr, SIGNAL(finished()), colorCntr, SLOT(deleteLater()));
connect(colorCntr, SIGNAL(results(int)), pxobj, SLOT(results(int)));
thread.start();
}
~ColorCounterController() {
thread.quit();
thread.wait();
qDebug() << QString("Controller quit wait");
//delete colorCntr; //err
}
我认为泄漏在ColorCounterController构造函数中:
colorCntr= new ColorCounter();
但如何避免呢?此代码导致错误。 在析构函数中:
//delete colorCntr; //err
并在构造函数中:
//connect(&thread, SIGNAL(finished()), &thread, SLOT(deleteLater()));
请帮忙!
P.S。
我改变了这个
delete[] *cntrl;
到这个
for (int i = 0; i < arrSize; i++){
if (cntrl[i])
delete cntrl[i];
}
cntrl之前的所有指针的和NULL [cnt2%arrSize]
没有任何改变
P.P.S。 如果您想为此问题做出贡献: https://github.com/ivanesses/curiosity
答案 0 :(得分:1)
2个问题导致泄漏:
新ColorCounterController对象的指针将永远丢失(并且它们的内存泄漏),因为“for”循环的主体将运行N次(N = box * box),创建N个ColorCounterController对象但仅指向8它们将适合您稍后用于删除对象的数组。
cntrl是一个指针数组。你需要遍历它并在每个元素上调用delete(plain delete,而不是delete [])。
:必须使用imageThread.release();而不是imageThread.deallocate()