2008年7月23日 星期三

資料結構操作及運算-資料結構的記憶體釋放

這裡就要講到所有資料結構記憶體釋放的問題了,這裡面所有的資料結構,包括視窗的建立,都是跟作業系統借空間的,尤其是IplImage結構跟CvMat結構的宣告,為圖形的存取,會佔去的是大量的空間,對於未先釋放記憶體,在任意配置空間進去,會造成Memory Leak,也就是記憶體漏失,遺失的記憶體部分就變成是垃圾空間了,找不到位址存取它,而程式也不能使用它,它也會永遠卡死在那邊直到程式關閉,在程式關閉前也不可能會有記憶體回收的動作,因為他是被認定為可存取的但是找不到指標位址,這種問題尤其在圖形的IplImage結構跟CvMat結構的使用較嚴重,一次卡死的記憶體都快1Mb,因為圖形矩陣的資料空間是很耗記憶體的,以下用一個視訊的使用範例.

MemoryLeak程式範例
#include <cv.h>
#include <highgui.h>
#include <stdio.h>


int main()
{
    CvCapture *capture;
    IplImage *frame,*frame1,*frame2;

    frame1=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3);
    frame2=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3);

    capture =cvCaptureFromCAM(0);

    cvNamedWindow("Webcam",0);

    while(true)
    {
        frame = cvQueryFrame(capture);
        cvSub(frame,frame1,frame2);
        cvAdd(frame2,frame,frame2);
        cvFlip(frame2,frame2,0);  // frame2->origin=1;

        cvShowImage("Webcam",frame2);

        if(cvWaitKey(10)>=0)    break;

        printf("%d",frame->origin);
        printf("%d",frame2->origin);

        frame1=cvCloneImage(frame);

    }
    cvReleaseCapture(&capture);
    cvDestroyWindow("Webcam");
}

執行結果:


這是一支很恐怖的程式,因為重點在於最下面的程式片段

frame1=cvCloneImage(frame);

每10毫秒製造了900kb的記憶體!它將frame資料結構的整段資料複製給frame1,而造成frame1之前的圖片位址被捨棄,這邊的捨棄是製造的空間未消失,在記憶體內佔據了一段,而且永遠無法被移除及使用,除非關閉這個程式,長時間下來這支程式會越來越肥,甚至超越作業系統核心記憶體的空間,長時間的使用其他在作業系統底下的程式會被分頁替換磁碟內,因此會造成其他程式開啟跟執行速度變慢,因為他必須重新重磁碟裡提取所需要的分頁,但是隨時都會被再度放入磁碟,而時間在久遠點,會造成輾轉現象(trashing),作業系統會不斷的重複的做無意義的分頁替換榨取空間,CPU使用率下降,這就是所謂的死當.而在這邊,這支程式的分頁錯誤及分頁錯誤差異則是正常現象.

但是,對於靜態圖片的使用上是沒多大的問題的,只要不是長時間的使用,程式用完馬上關閉,是不需要介意這種事的,因為該程式的分頁表被取消,可以在程式關閉的時候分頁就視為未使用的(但是原始資料還在).如果對靜態圖片來講,就可以只做釋放佔較大記憶體空間的結構,就如IplImage及CvMat還有視窗空間.



1 意見:

匿名 提到...

請問一下

我自己也遇到這種問題

不知道有什麼其他辦法可以解決嗎?

因為我是需要用到Webcam去做影像處理

會大量的應用到cvCreateImage()

 

Copyright 2008-2009,yester