2017-07-25 62 views
0

我多次打電話這段代碼得到一個內存泄漏:Gdiplus ::位圖:: FromHBITMAP內存泄漏

ULONG_PTR gdiplusToken; 
int screen_height; 
int screen_width; 

CVCamStream::CVCamStream(HRESULT *phr, CVCam *pParent, LPCWSTR pPinName) : CSourceStream(LPCSTR(FILTER_NAME),phr, pParent, pPinName), m_pParent(pParent) 
{ 
    hdc = GetDC(NULL); 

    Gdiplus::GdiplusStartupInput gdiplusStartupInput; 
    ULONG_PTR gdiplusToken; 
    GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); 

    screen_height = GetSystemMetrics(SM_CYVIRTUALSCREEN); 
    screen_width = GetSystemMetrics(SM_CXVIRTUALSCREEN); 
} 

CVCamStream::~CVCamStream() 
{ 
    Gdiplus::GdiplusShutdown(gdiplusToken); 
    DeleteDC(hdc); 
} 

HRESULT CVCamStream::FillBuffer(IMediaSample *pms) 
{ 
    REFERENCE_TIME rtNow; 
    REFERENCE_TIME avgFrameTime = ((VIDEOINFOHEADER*)m_mt.pbFormat)->AvgTimePerFrame; 

    static clock_t refClock = clock(); 
    double elapsed = (clock() - refClock)/(double)CLOCKS_PER_SEC; 

    rtNow = m_rtLastTime; 
    m_rtLastTime += avgFrameTime; 
    pms->SetTime(&rtNow, &m_rtLastTime); 
    pms->SetSyncPoint(TRUE); 

    HDC memdc = CreateCompatibleDC(NULL); 

    CImage image; 
    image.Create(screen_width, screen_height, 24); 
    SelectObject(memdc, image); 

    BYTE *pData; 
    pms->GetPointer(&pData); 
    long lDataLen = pms->GetSize(); 

    Gdiplus::Bitmap *bitmap = new Gdiplus::Bitmap(screen_width, screen_height, PixelFormat24bppRGB); 

    BitBlt(memdc, 0, 0, screen_width, screen_height, hdc, 0, 0, SRCCOPY); 
    DeleteDC(memdc); 

    // memdc is already deleted 
    bitmap->FromHBITMAP(image, NULL); 

    delete bitmap; 
    image.Destroy(); 
    DeleteObject(image); 
    DeleteDC(memdc); 

    return NOERROR; 
} 

但每一次的RAM使用量增加。違規行是FromHBITMAP()函數,因爲註釋它沒有更多的泄漏。

我知道FromHBITMAP()創建了一個位圖的副本,但我想我釋放了所有的回憶!

這裏有什麼問題?

+2

此代碼不能編譯。 「位圖」類型是錯誤的。如果它是一個指針(由'new' init猜測),那麼你應該刪除它。也沒有'hdc'清理。 – VTT

+0

修正了錯字並更新了代碼:內存泄漏仍然存在。 – Mark

+0

也許還有另一種方法來捕獲GDi +位圖中的屏幕內容? – Mark

回答

0

FromHBITMAP不取得傳遞的位圖句柄的所有權。您可以傳遞位圖句柄,該實例仍屬於CImage實例。也according to MSDN

不要傳遞給位圖:: FromHBITMAP方法的GDI位圖或GDI調色板是當前(或以前)選入設備上下文。

而你打電話給它,而image仍然被選入memdc

+0

我必須使用'memdc'作爲'BitBlt()'。我試圖在調用'FromHBITMAP'之前將其刪除,並且我還將'image.Detach()'更改爲'image'。同樣的行爲。 – Mark

+0

圖像仍然被選入DC的第一件事情是它應該不是。代碼構成實際上是否完整?你已經添加了關於析構函數和構造函數的註釋,所以我猜這裏有更多的代碼沒有顯示。 – VTT

+0

請看看更新的代碼。 「隱藏」代碼與圖像處理無關。 – Mark