前一天把系统整个重写了一遍,脉络清晰了很多,也终于解决了以前很多崩溃,异常退出的问题。这里小小总结一下自己遇到的麻烦。

1、内存泄露

内存泄露是说没有释放已经不能使用的内存,这里一般指堆的内存才需要显示的释放。比如用malloc,calloc,realloc,new分配的内存是在堆上的,需要用free,delete显示的回收。内存泄露最明显的一是程序很慢,在运行程序时你可以启动任务管理器,会看到程序占用的内存一直“砰砰砰”的往上涨:


opencv缓冲区 opencv释放内存_OpenCV

最后直接崩溃,或者你关闭程序的时候也会异常退出,出现

Debug Assertion Failed!
Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)

之类的问题。





opencv缓冲区 opencv释放内存_OpenCV_02

除了new的对象我们知道要delete。OpenCV中使用cvCreateImage()新建一个IplImage*,以及使用cvCreateMat()新建一个CvMat*,都需要cvReleaseImage()  cvReleaseMat()显示的释放



1. IplImage* subImg=cvCreateImage( cvSize((img->width)*scale,(img->height)*scale), 8, 3 );  
2. CvMat *tempMat=cvCreateMat((img->width)*scale,(maxFace->height)*scale,CV_MAKETYPE(image->depth,image->nChannels));  
3. cvReleaseImage(&subImg);  
4. cvReleaseMat(&tempMat);


另外一些函数要用到 CvSeq*来存放结果(通常这些都要用cvCreateMemStorage()事先分配一块内存CvMemStorage*),都要是释放掉相应的内存,这是很难找的。

比如从二值图像中寻找轮廓的函数cvFindContours():


opencv缓冲区 opencv释放内存_OpenCV_02

除了new的对象我们知道要delete。OpenCV中使用cvCreateImage()新建一个IplImage*,以及使用cvCreateMat()新建一个CvMat*,都需要cvReleaseImage()  cvReleaseMat()显示的释放


1. IplImage* subImg=cvCreateImage( cvSize((img->width)*scale,(img->height)*scale), 8, 3 );  
2. CvMat *tempMat=cvCreateMat((img->width)*scale,(maxFace->height)*scale,CV_MAKETYPE(image->depth,image->nChannels));  
3. cvReleaseImage(&subImg);  
4. cvReleaseMat(&tempMat);


另外一些函数要用到 CvSeq*来存放结果(通常这些都要用cvCreateMemStorage()事先分配一块内存CvMemStorage*),都要是释放掉相应的内存,这是很难找的。

比如从二值图像中寻找轮廓的函数cvFindContours():





1. CvMemStorage* m_storage=cvCreateMemStorage(0);  
2. CvSeq * m_contour=0;  
3. cvFindContours( img, m_storage, &m_contour, sizeof(CvContour), CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0));  
4. //释放内存  
5. cvReleaseMemStorage(&m_storage);


以及人脸识别中检测人脸的函数:



    1. CvMemStorage* m_storage=cvCreateMemStorage(0);  
    2. CvHaarClassifierCascade* cascade = (CvHaarClassifierCascade*)cvLoad( cascade_name, 0, 0, 0 );  
    3. CvSeq* faces = cvHaarDetectObjects( img, cascade, m_storage,1.1, 2, 0,cvSize(30, 30) );  
    4. //释放内存  
    5. cvReleaseMemStorage( &faces->storage);  
    6. cvReleaseHaarClassifierCascade( &cascade );



    注意这里我们可以使用


    cvReleaseMemStorage( &faces->storage);


    来释放m_storate,也可以使用:


    cvReleaseMemStorage(&m_storage);


    释放内存,这是等效的,但一定不要用两次!!


    2、一块内存多次释放

    对应没有释放内存,对应就是一个内存释放多次,如同上面的 cvReleaseMemStorage用了两次。可能报错的地方:


    1. __declspec(noinline)  
    2. void __cdecl _CRT_DEBUGGER_HOOK(int _Reserved)  
    3. {  
    4. /* assign 0 to _debugger_hook_dummy so that the function is not folded in retail */  
    5.     (_Reserved);  
    6.     _debugger_hook_dummy = 0;  
    7. }

    或者: Unhandled exception at XXXXXXXXXX in XXX.exe: XXXXXXXXXXX: 堆已损坏。 


    opencv缓冲区 opencv释放内存_opencv缓冲区_04


    除了上述的MemStorge问题,使用cvQueryFrame()取出CvCapture*每帧图像,只需在最后释放CvCapture*,不需要释放IplImage*

    *这篇是以前写的,其实还是建议大家用C++接口的OpenCV,内存问题很少了~

    1. CvCapture* pCapture = cvCreateCameraCapture(-1);  
    2. IplImage* pFrame=cvQueryFrame( pCapture );  
    3. cvReleaseCapture(&pCapture);





    opencv缓冲区 opencv释放内存_OpenCV_02

    除了new的对象我们知道要delete。OpenCV中使用cvCreateImage()新建一个IplImage*,以及使用cvCreateMat()新建一个CvMat*,都需要cvReleaseImage()  cvReleaseMat()显示的释放



      1. IplImage* subImg=cvCreateImage( cvSize((img->width)*scale,(img->height)*scale), 8, 3 );  
      2. CvMat *tempMat=cvCreateMat((img->width)*scale,(maxFace->height)*scale,CV_MAKETYPE(image->depth,image->nChannels));  
      3. cvReleaseImage(&subImg);  
      4. cvReleaseMat(&tempMat);


      另外一些函数要用到 CvSeq*来存放结果(通常这些都要用cvCreateMemStorage()事先分配一块内存CvMemStorage*),都要是释放掉相应的内存,这是很难找的。

      比如从二值图像中寻找轮廓的函数cvFindContours():


        1. CvMemStorage* m_storage=cvCreateMemStorage(0);  
        2. CvSeq * m_contour=0;  
        3. cvFindContours( img, m_storage, &m_contour, sizeof(CvContour), CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0));  
        4. //释放内存  
        5. cvReleaseMemStorage(&m_storage);



        以及人脸识别中检测人脸的函数:




        1. CvMemStorage* m_storage=cvCreateMemStorage(0);  
        2. CvHaarClassifierCascade* cascade = (CvHaarClassifierCascade*)cvLoad( cascade_name, 0, 0, 0 );  
        3. CvSeq* faces = cvHaarDetectObjects( img, cascade, m_storage,1.1, 2, 0,cvSize(30, 30) );  
        4. //释放内存  
        5. cvReleaseMemStorage( &faces->storage);  
        6. cvReleaseHaarClassifierCascade( &cascade );


        注意这里我们可以使用


        cvReleaseMemStorage( &faces->storage);


        来释放m_storate,也可以使用:


        cvReleaseMemStorage(&m_storage);


        释放内存,这是等效的,但一定不要用两次!!


        2、一块内存多次释放

        对应没有释放内存,对应就是一个内存释放多次,如同上面的 cvReleaseMemStorage用了两次。可能报错的地方:



        1. __declspec(noinline)  
        2. void __cdecl _CRT_DEBUGGER_HOOK(int _Reserved)  
        3. {  
        4. /* assign 0 to _debugger_hook_dummy so that the function is not folded in retail */  
        5.     (_Reserved);  
        6.     _debugger_hook_dummy = 0;  
        7. }

        或者: Unhandled exception at XXXXXXXXXX in XXX.exe: XXXXXXXXXXX: 堆已损坏。 


        opencv缓冲区 opencv释放内存_opencv缓冲区_04


        除了上述的MemStorge问题,使用cvQueryFrame()取出CvCapture*每帧图像,只需在最后释放CvCapture*,不需要释放IplImage*


        1. CvCapture* pCapture = cvCreateCameraCapture(-1);  
        2. IplImage* pFrame=cvQueryFrame( pCapture );  
        3. cvReleaseCapture(&pCapture);


        *这篇是以前写的,其实还是建议大家用C++接口的OpenCV,内存问题很少了~