Ask Your Question

Revision history [back]

Crashes in Mat destructor

Hey :),

I'm an IT-student and was assigned with the task to implement a harris detector by hand, I'm allowed to use OpenCV for image loading and accessing. So the first step is to implement the image derivation. Not too hard of a task, I thought, and started writing the source. I coppied it all together in one file, to make it easier for you.

So my problem is: there is an exception in the mat-dtor when leaving the derivate() function (sometimes on the first call, sometimes on the seccond call) and I really have no Idea why. It also does not get caught by the catch(std::exception) ... . Here is the call-stack at the crash:

>   opencv_core300d.dll!cv::fastFree(void * ptr) Zeile 81   C++
    opencv_core300d.dll!cv::StdMatAllocator::deallocate(cv::UMatData * u) Zeile 218 C++
    opencv_core300d.dll!cv::MatAllocator::unmap(cv::UMatData * u) Zeile 63  C++
    opencv_core300d.dll!cv::Mat::deallocate() Zeile 434 C++
    Ex2.exe!cv::Mat::release() Zeile 668    C++
    Ex2.exe!cv::Mat::~Mat() Zeile 555   C++
    Ex2.exe!derivate(cv::Mat & source, cv::Mat & target, Direction dir) Zeile 88    C++
    Ex2.exe!main(int argc, char * * argv) Zeile 120 C++

I use OpenCV3 (I link against the debug build in debug mode, and against the release build in release mode, so thats not the source of the problem, btw) and VisualStudio2013.

Here is my source:

#include <iostream>
#include <chrono>

#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>

//#include "derivate.h"

using namespace std;
using namespace std::chrono;

class FastAccess
{
public:
    FastAccess(cv::Mat &image)
    {
        auto h = image.size().height;
        ptr = new int*[h];

        for (int row = 0; row < h; ++row)
            ptr[row] = image.ptr<int>(row);

    }

    ~FastAccess()
    {
        //delete[] ptr;
    }

    int *operator [] (size_t row)
    {
        return ptr[row];
    }

private:
    int **ptr;
};

void pad_image(cv::Mat &source, cv::Mat &target, bool isHorz)
{
    int top, bot, left, right;

    top = bot = (isHorz) ? 0 : 1;
    left = right = (isHorz) ? 1 : 0;

    cv::copyMakeBorder(source, target, top, bot, left, right, IPL_BORDER_CONSTANT, 0);
}

enum class Direction
{
    Horizontal, Vertical
};

void derivate(cv::Mat &source, cv::Mat &target, Direction dir)
{
    bool isHorz = (dir == Direction::Horizontal);
    cv::Mat workingImage;
    pad_image(source, workingImage, isHorz);
    target.create(source.size(), source.type());
    unsigned startW, startH, targetW, targetH;

    if (isHorz)
    {
        startW = 1; startH = 0;
        targetW = source.size().width + 1;
        targetH = source.size().height;
    }
    else
    {
        startW = 0; startH = 1;
        targetW = source.size().width;
        targetH = source.size().height + 1;
    }

    FastAccess faDerivative(target);
    FastAccess faWImage(workingImage);

    for (auto row = startH; row < targetH; ++row)
    {
        for (auto col = startW; col < targetW; ++col)
        {
            faDerivative[row - startH][col - startW] = isHorz ?
                faWImage[row][col + 1] - faWImage[row][col - 1] :
                faWImage[row + 1][col] - faWImage[row - 1][col];
        }
    }
}

int main(int argc, char **argv)
{
    try
    {
        if (argc != 2)
        {
            cout << " Usage: Pass in the path of the image you want to load" << endl;
            return -1;
        }

        cv::Mat image = cv::imread(argv[1]);
        cv::imshow("Orignal", image);
        cv::waitKey(0);

        cv::Mat grayImage;
        if (image.channels() == 1)
            grayImage = image;
        else
            cv::cvtColor(image, grayImage, CV_BGR2GRAY);

        cout << "Beginning Derivate" << endl;
        auto start = high_resolution_clock::now();
        cv::Mat dx;
        derivate(image, dx, Direction::Horizontal);
        auto end = high_resolution_clock::now();
        cout << "x-Ableitung: " << duration_cast<milliseconds>(end - start).count() << "ms" << endl;

        start = high_resolution_clock::now();
        cv::Mat dy;
        derivate(image, dy, Direction::Vertical);
        end = high_resolution_clock::now();
        cout << "y-Ableitung: " << duration_cast<milliseconds>(end - start).count() << "ms" << endl;

        cv::imshow("dx", dx);
        cv::imshow("dy", dy);

        cv::waitKey(0);
        return 0;
    }
    catch (std::exception &e)
    {
        cerr << e.what() << endl;
        cin.get();
        return -1;
    }
}

There is also another small problem. I use the FastAccess class, because I was told that using a 2Dimensional array filled with the pointes of an image is dramatically faster than using the Mat::at() method. Originally I used a function to generate the 2D array:

int** get_fast_access(cv::Mat &image)
{
    int **ptr;
    auto h = image.size().height;
    ptr = new int*[h];

    for (int row = 0; row < h; ++row)
        ptr[row] = image.ptr<int>(row);

    return ptr;
}

but on the delete[] ptr; call it crashed (which used to be the last line of the derivate() function) Since I thought "maybe that crash has to do with the new beeing in the function, and the delete outside of it" I wrapped it in a class. But that didn't help either. Because if I dont out-comment the dtor of FastAccess it will crash there, although I'm quite sure that that delete[] call belongs there, and without it, it will produce a memory leak.

I hope you can help, and sorry for the extremly long post.

Best regards

Uzaku