Search code examples
c++visual-c++opencvheap-corruption

Why heap corruption when returning an object Mat?


I don't understand why I get a corrupted heap error with this program (I'm using OpenCV for the class Mat):

class A {
    private:
    Mat image;      

    static UINT ThreadProc( LPVOID pParam ) {
        A* pThis= (ClientNetwork*)pParam;
        UINT nRet= pThis->DoThreadProc();     // get out of 'static mode'
        return( nRet );
    }
    UINT ClientNetwork::DoThreadProc() {
         vector<uchar> vect;
         while(1) {
             /**** initialize vect and get the image data to decode ****/

             decode(vect);
         }
    }

    public:
    void decode(const vector<uchar>& vectorData){image=imdecode(vectorData, CV_LOAD_IMAGE_COLOR);}
    Mat get_image(){return image;}
    void start() {m_pcThread= AfxBeginThread(ThreadProc, this );}
}

int main() {
    A* a = new A();
    a->start();
    while(1) {
        Mat image = a->get_image();
    }
    delete a;
    return 0;
}

It seems that the error come from Mat image = a->get_image(); because if I return a reference instead of a copy of the object, I don't have error anymore:

Mat* get_image(){return &image;}

and

Mat* image = a->get_image();

I read that returning a copy of an object is more elegant in C++ than a reference. So I would like to know what is wrong.

EDIT: Visual studio breaks at a->decode(vect) but it happens only when I return an object and not a reference.

EDIT 2: I edited the code to reflect the full program. I think the problem comes from the shared object a which is copy and modified at the same time. I will see if the problem still occur using a mutex.


Solution

  • The copy constructor of cv::Mat does not create a deep copy of the image. It just creates a reference to the original Mat and increases its reference count. In the following function of the class, the return statement calls the copy constructor, returning a reference to the original image, which is the probable cause of heap corruption:

    Mat get_image(){ return image; }
    

    You should return a deep copy of the image as follows, so that the original image does not get modified accidentally.

    Mat get_image(){ return image.clone(); }