2017-08-08 54 views
0

我看到一個問題,我無法重新選擇DC上的原始位圖,導致內存泄漏。指向原始位圖的指針在整個程序中保持不變,但數據(來自CBitmap :: GetBitmap)從單色變爲其他。我不知道位圖實際更改的時間,但系統中的某些內容正在導致它。GDI:原始DC位圖發生變化,無法恢復

CBitmap* cMyClass::mpOldBitmap; 
CDC cMyClass::mCanvasDc; 
CBitmap cMyClass::mCanvasBmp; 

void cMyClass::Init() 
{ 
    // One-time initialization 
    CDC* pDc = GetDC(); 
    mCanvasDc.CreateCompatibleDC(pDc); 
    mCanvasBmp.CreateCompatibleBitmap(pDc, 10, 10); 
    mpOldBitmap = mCanvasDc.SelectObject(&mCanvasBmp); 
    ReleaseDC(pDc); 

    BITMAP bitmap; 
    mpOldBitmap->GetBitmap(&bitmap); // A monochrome bitmap, as expected. 
} 

void cMyClass::Recreate(int newW, int newH) 
{ 
    // 1. Delete existing bitmap: 
    if (mpOldBitmap) 
    { 
     BITMAP bitmap; 
     mpOldBitmap->GetBitmap(&bitmap); // This is no longer the monochrome bitmap. It is 8bpp, with random size. 

     CBitmap* pCurrBmp = mCanvasDc.SelectObject(mpOldBitmap); // This fails (NULL). I can't de-select my bitmap. 
     mCanvasBmp.DeleteObject(); // This fails too, causing memory leak. Actually, it fails in CE6, but not in Win32. Regardless, both platforms will have a memory leak. 
    } 

    // 2. Recreate the bitmap with new size: 
    { 
     CDC* pDc = GetDC(); 
     mCanvasBmp.CreateCompatibleBitmap(pDc, newW, newH); 
     ReleaseDC(pDc); 
    } 

    // 3. Finalize 
    mpOldBitmap = mCanvasDc.SelectObject(&mCanvasBmp); 
} 
  1. 任何已知的場景中會發生這種情況?
  2. 任何調試提示在位圖數據更改時中斷?

注:在代碼中,我提到「這個失敗」。我刪除了返回值的斷言,以使代碼可讀。


編輯:我用來解決它的解決方案是使用CDC:SaveDC和CDC :: RestoreDC,而不是存儲指針。內存泄漏消失了,並且每個GDI調用都通過了。但我仍然很好奇爲什麼原始代碼泄漏。據我所知,指向默認位圖的指針應該是默認的單色位圖,可能是GDI世界中的全局位圖

+1

[mcve]必需。 – IInspectable

+0

我認爲你的問題是你不能像這樣操作(重新創建)一個實例變量。您需要一個指向CBitmap的指針,即CBitmap * mCanvasBmp並「刪除」它,並且每次重新創建它就像mCanvasBmp = new CBitmap。 – VuVirt

回答

-1

讓我們來看看OP的代碼。

mpOldBitmap = mCanvasDc.SelectObject(mCanvasBmp); 

由於mCanvasBmp是一個的CBitmap對象(未指針的CBitmap),第一種稱爲HGDIOBJ操作者,然後CDC ::選擇對象(HGDIOBJ)它返回HGDIOBJ和不的CBitmap *。這應該會導致轉換編譯器錯誤。如果將返回的值轉換爲CBitmap *也是錯誤的。

擺脫問題的正確方法是傳遞一個指針。

mpOldBitmap = mCanvasDc.SelectObject(& mCanvasBmp); 

這種情況將被稱爲CDC ::選擇對象(*的CBitmap pBitmap)它返回一個的CBitmap *

//我希望它很清楚。 :)

+0

對不起,這是我的一個錯字,試圖簡化SO的代碼。我已更正說明。我還添加了我找到的解決方案,但我仍然很好奇爲什麼原版不起作用。 – Ryuu