2016-02-26 25 views
0

不知道爲什麼,但即時通訊使用Deleaker插件來檢測內存泄漏。 在我調試代碼構建其說我必須在GetDC 然後在發佈å存儲泄漏建立跟它我在CreateCompatibleDCHDC內存泄漏

泄漏是這些真實泄漏還是假的? 當我的類關閉時,我的刪除對象被調用。

HDC hdc = GetDC(_hWnd); 
    _hdcMem = CreateCompatibleDC(hdc); 
    HBITMAP hbmOld = (HBITMAP)SelectObject(_hdcMem, _hBitmap); 

    while (_execute.load(std::memory_order_acquire)) 
    { 
     func(); 

     BitBlt(hdc, 0, 0, _Width, _Height, _hdcMem, 0, 0, SRCCOPY); 
    } 

    SelectObject(_hdcMem, hbmOld); 
    DeleteDC(_hdcMem); 
    DeleteObject(hbmOld); 
    DeleteObject(_hBitmap); 
    DeleteDC(hdc); 
+0

你也試過Valgrind嗎?如果報道有兩種工具泄漏,它不是確定性的,但它會給你一個更好的主意。 – erip

+0

不知道那個人會給它以前的感謝 – ramafe

+0

我從來沒有聽說過德萊克,但我知道Valgrind許多發誓。我仍然有Valgrind報告誤報(特別是在多線程應用程序中),但總的來說這是一個很好的工具。 – erip

回答

3

必須使用ReleaseDC()以釋放GetDC()返回的HDC。

請勿刪除SelectObject()返回的hbmOld。只需選擇它回到HDC並讓ReleaseDC()處理其刪除。

+0

感謝錯過了releaseDC直到它仍然得到相同的泄漏 – ramafe

3

經過GetDC後,您必須致電ReleaseDC - 而不是DeleteDCDeleteDC僅與CreateCompatibleDC一起使用。如果你忘記了,這一切都在the documentation中詳細說明。

此外,您錯誤地清理您的設備上下文。您將句柄保存到舊對象的原因是,您可以重新選擇它們到DC中。你不能刪除它們!選中到設備上下文中的對象不能被刪除 - 它們正在使用中。 (如果你檢查這些API函數的返回值,你會知道,因爲他們會返回一個錯誤。)

的代碼應該是這樣的:

HDC hdc = GetDC(_hWnd); 

_hdcMem = CreateCompatibleDC(hdc); 
HBITMAP hbmOld = (HBITMAP)SelectObject(_hdcMem, _hBitmap); 

while (_execute.load(std::memory_order_acquire)) 
{ 
    func(); 

    BitBlt(hdc, 0, 0, _Width, _Height, _hdcMem, 0, 0, SRCCOPY); 
} 

SelectObject(_hdcMem, hbmOld); 
DeleteObject(_hBitmap); 
DeleteDC(_hdcMem); 

ReleaseDC(_hWnd, hdc); 

這是我不清楚爲什麼當它們的作用域限於這一位代碼時,爲_hdcMem_hBitmap使用全局變量。你在頂部創建它們,並在底部銷燬它們,所以它們在此代碼之外是沒用的。您應該將其範圍限制在代碼的這一部分。能夠推理對象/變量的生命週期是跺出內存泄漏的關鍵。

請注意,使用將這些原生資源包裝在RAII fashion(構造函數獲取;析構函數發佈)中的庫將是一個絕妙的想法。它不僅可以讓您不必記住每次清理的細節,而且還可以確保您的代碼是異常安全的。如果func()要扔在這裏,你肯定會有內存泄漏。這是一個真的很好靜態分析儀會告訴你。

+0

即時使用全局變量_hdcMem和_hBitmap,因爲我使用他們其他地方,必須是我的檢漏儀,因爲它仍然說有泄漏 – ramafe

+1

你不除非你重用存儲在這些變量中的*值*,否則需要全局變量。你可以創建多個變量,但它對重用全局變量沒有任何好處。就泄漏而言,有可能(1)如我在答案中指出的那樣,如果發生異常,泄漏檢測器會報告泄漏的可能性;或者(2)您的項目中有其他代碼使用GDI對象,因此可能會泄漏。大概你沒有顯示*全部*的代碼... –