简体   繁体   English

OpenCV中的大量内存泄漏

[英]Huge memory leak in opencv

I've written a very very simple C++ program to read 600 video frames in a multi-threaded code. 我编写了一个非常非常简单的C ++程序,以多线程代码读取600个视频帧。 the problem is that when I release each of these frames the free memory size doesn't change! 问题是当我释放这些帧中的每一个时,可用内存大小不会改变! I'm using qt 4.8 and ubuntu 12.04 My Laptop Memory size is 8 GB so I don't have any memory shortage. 我正在使用qt 4.8和ubuntu 12.04。我的笔记本电脑内存大小为8 GB,所以我没有任何内存不足的情况。

each frame is 1.8 MB so the total size is 600*1.8 MB = 1080 MB 每个帧为1.8 MB,因此总大小为600 * 1.8 MB = 1080 MB

before running the program my memory free size is 6.8 GB but after running my code and letting it to finish I see the free memory size is 5.9 GB so I see there's a huge memory leak in the program. 在运行程序之前,我的可用内存大小为6.8 GB,但是在运行代码并完成之后,我看到可用内存大小为5.9 GB,因此我发现程序中存在大量内存泄漏。 I've run my code 1000 times and never saw my program crashes or face any problems so the code is okay. 我已经运行了1000次代码,却从未见到程序崩溃或遇到任何问题,因此代码还可以。

My code: 我的代码:

#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 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

Mainwindow.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;
}

Mainwindow.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

Definitions.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

I've read in some articles that opencv c++ version support memory management so we don't have to be worry about memory leaks. 我读过一些文章,其中提到opencv c ++版本支持内存管理,因此我们不必担心内存泄漏。

am I missing something here ? 我在这里想念什么吗? I've read these questions too but none of them worked for me this and this 我读过这些问题太多,但他们没有工作对我来说这个这个

Just one post amused me is SO and made me think if I have this problem in my code but I couldn't figure out. 只有一个帖子让我感到很有趣,让我思考代码中是否有这个问题,但我不知道。 this is the link 这是链接

I'll provide anything else if needed. 如果需要,我将提供其他任何信息。

EDITED: 编辑:

it's very interesting that if I add a Delay function in my imageloader class just after reading each frame the amount of memory leaks reduces !!! 有趣的是,如果我在读取每一帧后在imageloader类中添加Delay函数,则内存泄漏量将减少!!!

My new im_loader.cpp 我的新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 ...");
}

adding a 100 ms delay reduced the memory leakage to only 100 Mega Bytes instead of 1 Gigabyte !!! 增加100毫秒的延迟将内存泄漏减少到仅100兆字节,而不是1吉字节!

Finally, I found out what caused this memory leak ... as you can see in the im_loader class and specifically run() function I have this block of code: 最后,我找出了导致此内存泄漏的原因……正如您在im_loader类(尤其是run()函数)中所看到的,我具有以下代码块:

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

Since OpenCV use a reference counting procedure for cv::Mat object, input image is copied into Dataa variable and then into PD_Classifier. 由于OpenCV对cv :: Mat对象使用引用计数过程,因此将输入图像复制到Dataa变量中,然后复制到PD_Classifier中。 PD_Classifier gets deleted but Dataa no ! PD_Classifier被删除,但Dataa不! so when I removed this line and change the code to this the problem got solved: 所以当我删除这一行并将代码更改为此时,问题就解决了:

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

I thought that since Dataa is a local variable it will be deleted after exiting the run() function but it appears that although it gets deleted after exiting the function its data stays on memory. 我以为,由于Dataa是局部变量,因此在退出run()函数后将被删除,但是看来,尽管它在退出函数后被删除,但其数据仍保留在内存中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM