2011-08-18 77 views
7

我們正在從VC8升級到VC10,並發現一些似乎與CDialog相關的內存泄漏。下面的代碼使用一個只包含多個按鈕的CDialog演示了最簡單的例子。在此VC10泄漏,但在VC8它並不:VC10中的CDialog內存泄漏

for (int i = 0; i < 5000; ++i) { 
    CDialog* dialog = new CDialog; 
    dialog->Create(IDD_LEAKER, 0); 
    dialog->DestroyWindow(); 
    delete dialog; 
} 

內存使用量不斷上升和示例對話,我們有大約30按鈕泄漏MB的10秒。

請注意,以上是一個測試示例,我們已經剝離了所有對話處理代碼,在我們的真實代碼中我們有一個派生類並使用PostNcDestroy()。

奇怪的是既不下面的代碼示例中泄漏任何VC8或VC10:

CDialog* dialog = new CDialog; 
for (int i = 0; i < 5000; ++i) { 
    dialog->Create(IDD_LEAKER, 0); 
    dialog->DestroyWindow(); 
} 
delete dialog; 

for (int i = 0; i < 5000; ++i) { 
    CDialog* dialog = new CDialog; 
    delete dialog; 
} 

什麼是我們在這裏失蹤?

+0

- 爲什麼你需要1)創建' CDialog',2)創建5000個對話框,3)不使用ShowDialog或DoModal? – Ajay

+0

我認爲提問者詢問無模對話的具體問題,並簡單地提供了一些簡化代碼來解釋他所看到的問題:「請注意,上面是一個測試示例...」。我懷疑5000是一個任意數字,只是爲了強調症狀。 – Nick

+0

要回答:代碼是一種測試,任何人都可以插入Windows應用程序並使用自己的對話框進行測試。我們的對話恰好是無模式的,但是當用戶關閉它們時會被刪除和清理。我們的問題不僅在於內存泄漏,因爲這是壞的,而且還有一個事實,即如果您計算循環時間,每次迭代都會變得越來越長。 – lilburne

回答

7

這似乎是向下的方式,MFC管理其手柄地圖:

What is the lifetime of a CWnd obtained from CWnd::FromHandle?

如果等待足夠長的時間你的應用程序變得空閒時,你得到你的記憶回來了,也就是說,它不是真的是泄漏。但是,正如你所觀察到的,儘管Visual C++ 2010繼續消耗越來越多的內存 - 直到地圖在OnIdle()中被整理 - 這似乎不會在Visual C++ 2008中發生。

調試包含您的應用程序代碼確實顯示VC 10版本中HWND臨時映射中的對象數量遠多於VC 9版本中的對象。

處理映射代碼(winhand.cpp)在兩個版本之間似乎沒有改變,但MFC中有很多代碼使用它!

無論如何,假設你真的想像這樣運行你的程序 - 我猜你正在運行某種自動模式? - 那麼你會想要在適當的時間間隔強制垃圾收集。看一看MSDN上此項:

http://msdn.microsoft.com/en-us/library/xt4cxa4e(v=VS.100).aspx

的CWinThread ::的OnIdle()實際上調用這個整齊的事情了:只是出於好奇

AfxLockTempMaps(); 
AfxUnlockTempMaps(/*TRUE*/); 
+0

是的,似乎解決它。我們的自動測試系統運行1000個測試腳本,升級和降低表單,但不會進入空閒循環。在VC10中,如果在一個序列開始時運行需要1秒鐘,如果在最後運行則需要5或6秒。 – lilburne