Memory leak on Mat creation

asked 2013-07-11 13:00:26 -0500

B. Bogart gravatar image

Valgrind is telling me the following:

==8885== 458,704 bytes in 1 blocks are definitely lost in loss record 17,981 of 18,027
==8885==    at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8885==    by 0x33C0BA90: cv::fastMalloc(unsigned long) (in /usr/local/lib/libopencv_core.so.2.4.5)
==8885==    by 0x33C51BF1: cv::Mat::create(int, int const*, int) (in /usr/local/lib/libopencv_core.so.2.4.5)
==8885==    by 0x4196CD: cv::Mat::Mat(int, int, int, cv::Scalar_<double> const&) (mat.hpp:353)
==8885==    by 0x41BEA6: clustering::mergeImages(cv::Mat, cv::Mat, std::string, std::string, float, float) (clustering.cpp:128)
==8885==    by 0x41C582: clustering::mergePerceps(percepUnit, percepUnit, std::string) (clustering.cpp:205)
==8885==    by 0x41D6E5: clustering::cluster(std::list<percepUnit, std::allocator<percepUnit> >&, std::list<percepUnit, std::allocator<percepUnit> >&, std::string) (clustering.cpp:428)
==8885==    by 0x41FA45: segmentationClusteringThread::tick() (segmentationClusteringThread.cpp:351)
==8885==    by 0x41FF41: segmentationClusteringThread::threadedFunction() (segmentationClusteringThread.cpp:425)
==8885==    by 0x501AD2: ofThread::run() (in /home/bbogart/Projects/svn/Dreaming-Machine-3/trunk/DM/bin/DM)
==8885==    by 0x578E52: Poco::ThreadImpl::runnableEntry(void*) (in /home/bbogart/Projects/svn/Dreaming-Machine-3/trunk/DM/bin/DM)
==8885==    by 0x34E6BE99: start_thread (pthread_create.c:308)

Following is the mergeImages function:

Mat clustering::mergeImages(Mat scratch, Mat unit, const string maskOrImage, const string FGBG, const float scratchWeight, const float unitWeight) {

    int width, height, type;
    Mat merged, scratchImagePad, unitImagePad, scratchImage, unitImage;
    Mat *smallImage, *bigImage;

    // use the resolution and aspect of the largest of the pair.
    if (unit.cols > scratch.cols)
        width = unit.cols;
    else
        width = scratch.cols;

    if (unit.rows > scratch.rows)
        height = unit.rows;
    else
        height = scratch.rows;

    if (maskOrImage == "mask") 
        type = CV_8UC1; // single channel mask
    else if (maskOrImage == "image")
        type = CV_8UC3; // three channel image
    else
        cout << "maskOrImage is not 'mask' or 'image'\n";

    merged = Mat(height, width, type, Scalar::all(0));
    scratchImagePad = Mat(height, width, type, Scalar::all(0));
    unitImagePad = Mat(height, width, type, Scalar::all(0));

    // weight images before summation.
    scratchImage *= scratchWeight;
    unitImage *= unitWeight;

    // copy images into padded images.
    scratch.copyTo(scratchImagePad(Rect((scratchImagePad.cols-scratchImage.cols)/2,
                                             (scratchImagePad.rows-scratchImage.rows)/2,
                                              scratchImage.cols,
                                              scratchImage.rows)));


    unit.copyTo(unitImagePad(Rect((unitImagePad.cols-unitImage.cols)/2,
                                       (unitImagePad.rows-unitImage.rows)/2,
                                        unitImage.cols,
                                        unitImage.rows)));

    merged = scratchImagePad+unitImagePad;

    // blur mask on background objects
    if (maskOrImage == "mask" and FGBG == "BG") {
        gpu::GpuMat gInputImage, gOutputImage;
        gInputImage.upload(merged);
        gpu::blur(gInputImage, gOutputImage, Size(5,5)); // WAS Size(height*.15,width*.15); // blur with kernel to blow up to full size.
        gOutputImage.download(merged);

        gInputImage.release();
        gOutputImage.release();
    }

    return(merged);
}

I've already posted a general question about memory leaks at Mats here (http://answers.opencv.org/question/14798/what-is-the-best-practise-for-passing-cvmats/), but I wanted to concentrate on this specific code, since its the greatest "definite" leak according to valgrind.

Thank you.

edit retag flag offensive close merge delete

Comments

Well, if you're sure that this is a "definite" leak, it is better to report a bug at the code.opencv.org. And even better to work on a solution (in a form of pull request), since you already have all the environment ready for debug...

Valgrind builder is not added to the continuous integration system, but it should be added at some point. So, OpenCV may easily have a number of leaks... Thanks for the investigation!

Kirill Kornyakov gravatar imageKirill Kornyakov ( 2013-07-12 15:46:35 -0500 )edit

Thanks @Kirill Kornyakov. I'm sure there is a leak in the sense that I can see the amount of ram increasing and the eventual crash of the program. I'm not sure the leak is where valgrind says it is, but where else to start? All the leaks I've seen valgrind report in this program seem to result from cv::Mat::create(), so I'll just try a simple program that does nothing but create a bunch of Mats and see if it leaks, and then report that as a bug.

B. Bogart gravatar imageB. Bogart ( 2013-07-15 17:46:05 -0500 )edit

Putting this same code above in a separate program does not lead to a leak, memory usage is stable.

B. Bogart gravatar imageB. Bogart ( 2013-07-17 11:42:14 -0500 )edit