c++ - opencv中的巨大内存泄漏

标签 c++ qt opencv memory-leaks ubuntu-12.04

我编写了一个非常非常简单的 C++ 程序,用于在多线程代码中读取 600 个视频帧。问题是当我释放这些帧中的每一个时,可用内存大小不会改变! 我正在使用 qt 4.8 和 ubuntu 12.04 我的笔记本电脑内存大小是 8 GB,所以我没有任何内存不足。

每帧为 1.8 MB,因此总大小为 600*1.8 MB = 1080 MB

在运行该程序之前,我的可用内存大小为 6.8 GB,但在运行我的代码并让它完成后,我看到可用内存大小为 5.9 GB,因此我发现程序中存在巨大的内存泄漏。我已经运行我的代码 1000 次,从未见过我的程序崩溃或遇到任何问题,所以代码没问题。

我的代码:

#include "im_loader.h"

IM_Loader::IM_Loader(QObject *parent) :
    QThread(parent)
{
}


void IM_Loader::run()
{
    QString PATH = "/home/parsa/QtProjects/MonoSD/";
     {
     for(float i = 0 ; i < 1 ; i++)
       {
         QString Folder_Address = PATH + QString::number((int)i)+"/";
         QDir Mydir(Folder_Address);
         Mydir.setFilter(QDir::Files);
         QFileInfoList Vehicles_list = Mydir.entryInfoList();
         qDebug()<<"Address is: "<<Folder_Address<<"\n";
         qDebug()<<"Number of images are: "<<Vehicles_list.size()<<"\n";
         static int overall_counter = 0; //12451
         for(int j = 0 ; j < 600 ; j++)
           {
             if(!Stop_Disp)
             {
                QString address = Folder_Address + QString::number(overall_counter++) +".jpg";
                cv::Mat image = cv::imread(address.toUtf8().constData(),0);
                if(!image.data)
                {
                    qDebug()<<"Image Data is failed ... \n";
                    continue;
                }
                if(j%100==0)
                qDebug()<<"Folder "<<i<<" Image No. "<<j<<" is processed, Overall counter is: "<<overall_counter<<"\n";
                cv::Mat Dataaa;
                image.copyTo(Dataaa);
                QMutexLocker Locker(&Global_Mutex);
                PD_Classifier_VEC.push_back(Dataaa);
                Locker.unlock();
                }
            }
        }
     }
    qDebug("Im loader is exited now ...");
}

im_loader.h

#ifndef IM_LOADER_H
#define IM_LOADER_H


#include "Definitions.h"

class IM_Loader : public QThread
{
    Q_OBJECT
public:
    explicit IM_Loader(QObject *parent = 0);
    void run();
    bool Stop_Disp;
signals:

public slots:

};

#endif // IM_LOADER_H

主窗口.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
QTimer *Mytimer;
QMutex Global_Mutex;
IM_Loader IML;
std::vector<cv::Mat> PD_Classifier_VEC;
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    IML.start();
    Mytimer = new QTimer(this);
    Mytimer->singleShot(20000,this,SLOT(Clear_Vec()));
}

void MainWindow::Clear_Vec()
{
    qDebug()<<"PD_Classifier_VEC.SIZE IS: "<<PD_Classifier_VEC.size();
    for(int i = 0 ; i < PD_Classifier_VEC.size() ; i++)
    {
        QMutexLocker Locker(&Global_Mutex);
        PD_Classifier_VEC.erase(PD_Classifier_VEC.begin() + i);
        Locker.unlock();
        i--;
    }
   Mytimer->singleShot(10000,this,SLOT(Clear_Vec()));
}

MainWindow::~MainWindow()
{
    delete ui;
}

主窗口.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include "Definitions.h"

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    void Delay(int Milisecond_Delay);
public slots:
    void Clear_Vec();
private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

定义.h

#ifndef DEFINITIONS_H
#define DEFINITIONS_H
#include <QMainWindow>
#include <QThread>
#include <QTimer>
#include <QDebug>
#include <QDir>
#include <QMutex>
#include <QMutexLocker>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include "im_loader.h"

extern std::vector<cv::Mat> PD_Classifier_VEC;
extern QMutex Global_Mutex;
#endif // DEFINITIONS_H

我在一些文章中看到,opencv c++版本支持内存管理,因此我们不必担心内存泄漏。

我在这里遗漏了什么吗?我也读过这些问题,但没有一个对我有用 thisthis

只有一个帖子让我觉得很有趣,这让我觉得我的代码中是否有这个问题,但我想不通。 this is the link

如果需要,我会提供其他任何东西。

已编辑:

非常有趣的是,如果我在我的图像加载器类中添加一个延迟函数,就在读取每一帧之后,内存泄漏量就会减少!!!

我的新 im_loader.cpp

void IM_Loader::Delay(int Milisecond_Delay)
{
    double OneSecond = cv::getTickFrequency();
    int Milisecond = OneSecond/4000;

   for(double t1= 0 ; t1 < Milisecond_Delay ; t1++)
          for(double t2= 0 ; t2 < Milisecond; t2++);
}
void IM_Loader::run()
{
    QString PATH = "/home/parsa/QtProjects/FINAL_VLPR/LowSpeed/";//Dataset_PATH;
     //while(1)
     {
     for(float i = 0 ; i < 1 ; i++)
       {
         QString Folder_Address = PATH + QString::number((int)i)+"/";
         QDir Mydir(Folder_Address);
         Mydir.setFilter(QDir::Files);
         QFileInfoList Vehicles_list = Mydir.entryInfoList();
         qDebug()<<"Address is: "<<Folder_Address<<"\n";
         qDebug()<<"Number of images are: "<<Vehicles_list.size()<<"\n";
         static int overall_counter = 0; //12451
         for(int j = 0 ; j < 300 ; j++)
           {
             if(!Stop_Disp)
             {
                QString address = Folder_Address + QString::number(overall_counter++) +".jpg";
                cv::Mat image = cv::imread(address.toUtf8().constData(),0);
                Delay(100);
                if(!image.data)
                {
                    qDebug()<<"Image Data is failed ... \n";
                    continue;
                }
                if(j%100==0)
                qDebug()<<"Folder "<<i<<" Image No. "<<j<<" is processed, Overall counter is: "<<overall_counter<<"\n";
                cv::Mat Dataaa;
                image.copyTo(Dataaa);
                QMutexLocker Locker(&Global_Mutex);
                PD_Classifier_VEC.push_back(Dataaa);
                Locker.unlock();
                }
            }
        }
     }
    qDebug("Im loader is exited now ...");
}

添加 100 毫秒的延迟将内存泄漏减少到仅 100 兆字节而不是 1 千兆字节!!!

最佳答案

最后,我找出了导致此内存泄漏的原因...正如您在 im_loader 类中看到的,特别是 run() 函数,我有这段代码:

 cv::Mat Dataaa;
 image.copyTo(Dataaa);
 QMutexLocker Locker(&Global_Mutex);
 PD_Classifier_VEC.push_back(Dataaa);
 Locker.unlock();

由于 OpenCV 对 cv::Mat 对象使用引用计数过程,因此输入图像被复制到 Dataa 变量中,然后复制到 PD_Classifier 中。 PD_Classifier 被删除但 Dataa 没有!所以当我删除这一行并将代码更改为此时,问题就解决了:

  QMutexLocker Locker(&Global_Mutex);
  PD_Classifier_VEC.push_back(image);
  Locker.unlock();

我认为因为 Dataa 是一个局部变量,所以它会在退出 run() 函数后被删除,但看起来虽然它在退出函数后被删除,但它的数据保留在内存中。

关于c++ - opencv中的巨大内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24029649/

相关文章:

c++ - OpenCV:检查像素是否在边界矩形内,由等高线分隔

c++ - 如何使用 `std::set` 将语法解析为 `boost::spirit` ?

c++ - 有关运动的信息。 QT C++

c++ - 使用 opencv 3.0 beta 校准鱼眼镜头

c++ - 如何在 Qt 中管理文件(替换、删除...)?

c++ - Qt 4.8 用于旋转qgraphicsitem的Qtransform

python - 无法访问 GetCaptureProperty 或 python opencv 中的任何类似函数

c++ - 访问类似单例的静态成员的段错误

c++ - 变量参数列表如何与 C++ 中的重载对象一起使用?

c++ - mac osx 10.7 中的 g++