2015-08-08 420 views
0

任何人都有這個問題,無論如何我沒有找到答案。代碼很簡單:CreateIconFromResource在被調用數千次後返回NULL和UI崩潰

void CbDlg::OnBnClickedOk() 
{ 
    for(int i=0; i<1000; i++) 
    { 
     HRSRC hRes = ::FindResource(NULL, MAKEINTRESOURCE(IDR_MAINFRAME), RT_GROUP_ICON); 
     HGLOBAL hResLoad = ::LoadResource(NULL, hRes); 
     BYTE* pIconBytes = (BYTE*)::LockResource(hResLoad); 
     int nId = ::LookupIconIdFromDirectory(pIconBytes, TRUE); 
     hRes = ::FindResource(NULL, MAKEINTRESOURCE(nId), RT_ICON); 
     DWORD read = ::SizeofResource(NULL ,hRes); 
     hResLoad = ::LoadResource(NULL, hRes); 
     pIconBytes = (BYTE*)::LockResource(hResLoad); 
     if(pIconBytes != NULL) 
     { 
      HICON hIcon = ::CreateIconFromResource(pIconBytes, read, TRUE, 0x00030000); 
      DWORD e = ::GetLastError(); 
      if(hIcon != NULL) 
      { 
       ::DestroyIcon(hIcon); 
      } 
     } 
    } 
} 

如果我點擊確定按鈕四次(在我的電腦),CreateIconFromResource開始返回NULL(它之前的工作很好,我甚至可以畫出來的圖標)。至於GetLastError,無論CreateIconFromResource是否返回NULL,它總是返回6。

當這個問題發生時,如果我拖動標題欄移動,UI崩潰,請參閱圖片。 UI crash

當然,您可以理解這段代碼只是一個演示,我的真實業務需要像這樣調用CreateIconFromResource幾千次。根據Hans的建議,我繼續跟蹤Handles/USER Objects/GDI對象,發現USER對象增長1000,而GDI對象增長2000對每次點擊OK按鈕(手柄沒有增長),並且當問題發生時GDI對象是9999。但是當我完成使用時,如何正確釋放它們?我一次沒有使用太多,但需要加載,釋放,再次加載,再次釋放......就像這個演示。作爲MSDN文檔,我爲每個HICON調用了DestroyIcon。我還需要做什麼,最終釋放USER/GDI對象?

+0

您可能泄漏手柄,當您泄漏10,000個手錶時,節目結束。 –

+0

@Hans,謝謝你的建議,我發現它是USER/GDI對象泄漏的,但我仍然有問題,在我的文章中更新。 – zhiyazw

回答

0

我找到了答案。成功或失敗都歸功於MSDN。

它說:

的CreateIconFromResource函數調用CreateIconFromResourceEx傳遞LR_DEFAULTSIZE | LR_SHARED爲標誌」 AND 「不要使用此功能(DestroyIcon)摧毀一個共享圖標

但還說:

當您完成使用該圖標時,使用CreateIconFromResource文檔中的DestroyIcon函數」將其銷燬。

其實第二種說法是錯誤的。

因此,解決方案是,使用CreateIconFromResourceEx而不使用LR_SHARED,並使用每個HICON的DestroyIcon。

相關問題