【问题标题】:How to remove memory leak in Qthreads? 12+Gb leak如何消除 Qthreads 中的内存泄漏? 12+Gb 泄漏
【发布时间】:2015-10-14 02:47:35
【问题描述】:

我正在尝试加快我的 (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()));

请帮忙!

附言

我改变了这个

delete[] *cntrl;

到这里

    for (int i = 0; i < arrSize; i++){
    if (cntrl[i])
        delete cntrl[i];
    }

cntrl[cnt2%arrSize]之前的所有指针都为NULL

没有改变

附言 如果您想为这个问题做出贡献: https://github.com/ivanesses/curiosity

【问题讨论】:

  • 删除colorCntr有什么错误;造成?它是编译器还是运行时?你使用什么编译标志?另外...您能否提供更多的未标记、无标题图表来表示内存泄漏? faculty.spokanefalls.edu/InetShare/AutoWebs/AsaB/GoodGraphs.pdf
  • 运行时错误读取访问冲突snag.gy/iyNku.jpg
  • 关于图表。对不起那一团糟。它只是表明我在 1 分钟内失去了近一半的内存 (8/16Gb)。
  • "你使用什么编译标志?" - 我使用来自 VS2013 的编译器 x64/vc12 和 Qt 默认设置 这是 Qt QT += core gui greaterThan(QT_MAJOR_VERSION, 4) 中的一些 .pro 设置:QT += widgets TARGET = Curiosity TEMPLATE = app
  • 为什么不使用内存分析器?从代码中很难理解可能是什么问题:原始指针等。我知道这是 Qt 风格,但无论如何......试试探查器!

标签: c++ multithreading performance qt memory-leaks


【解决方案1】:

2个问题导致泄漏:

  1. 指向新 ColorCounterController 对象的指针将永远丢失(并且它们的内存泄漏),因为“for”循环的主体将运行 N 次 (N=box*box) 创建 N 个 ColorCounterController 对象但仅指向 8它们中的一部分将适合您稍后用于删除对象的数组。

  2. cntrl 是一个指针数组。您需要遍历它并在它的每个元素上调用 delete(纯删除,而不是 delete[])。

  3. 由 OP 发现:必须使用 imageThread.release();而不是 imageThread.deallocate()

【讨论】:

  • 我明白为什么stackoverflow.com/a/21731939/5148638 但是泄漏仍然存在 我没有改变我为 (int i = 0; i 之前开始的所有指针
  • 抱歉,没有sscce.org,这个问题似乎无法再回答了。
  • 如果您无法轻松创建显示问题的代码的最小版本,请考虑分配的内存块的预期/必要生命周期,并将其与实际生命周期进行比较。当你中断程序时它可能看起来像一个“泄漏”,而如果它运行它应该执行删除循环 - 是吗?最后一点可以通过调试器断点或通过 printf-debugging 到某个日志文件来检查。祝你好运!
  • 另外,在删除 ptr 之前不要检查 null - 删除 null 是完全无害的 - 在删除时将 ptr 设置为 null!以防万一有人错误地尝试再次删除它(将是运行时错误)或通过 ptr 读/写内存(更严重的运行时错误)。取消引用 null ptr 也将是一个运行时错误,但至少行为将是确定性的并且更易于调试。你会得到不确定的行为,因为进程使用的原始内存通常是未初始化的,并且包含随机垃圾,每次执行都可能不同。
  • @V-R:“我不明白你为什么要动态分配所有这些新的和新的 ColorCounterController 对象”可能是 Qt 的误用技术。 Qt 跟踪派生自QObject/QWidget 的类的所有权。如果对象具有指定的所有者,则在所有者销毁时将其删除。但是,我没有看到为实例 ColorCounter 指定所有者(这通常在构造函数中完成),而且由于没有来源,我没有理由认为它们是从 QObject 派生的。
猜你喜欢
  • 1970-01-01
  • 2017-05-10
  • 1970-01-01
  • 1970-01-01
  • 2019-04-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-06
相关资源
最近更新 更多