Утечки памяти CDialog в VC10 - PullRequest
       35

Утечки памяти CDialog в VC10

7 голосов
/ 18 августа 2011

Мы выполняем обновление с VC8 до VC10 и обнаружили ряд утечек памяти, которые, по-видимому, связаны с CDialog.Простейший пример этого демонстрируется с помощью следующего кода с использованием CDialog, который просто имеет несколько кнопок.В VC10 это происходит с утечкой, но в VC8 это не так:

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

Использование памяти продолжает расти, и в нашем примере с примерно 30 кнопками утечка составляет 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;
}

Чего нам здесь не хватает?

1 Ответ

7 голосов
/ 19 августа 2011

Это похоже на то, как MFC управляет своими картами дескрипторов:

Каково время жизни CWnd, полученного из CWnd :: FromHandle?

Если вы достаточно долго ждете, пока ваше приложение станет бездействующим, вы все же вернете свою память, т. Е. На самом деле это не утечка. Однако, как вы заметили, хотя Visual C ++ 2010 продолжает потреблять все больше и больше памяти - пока карты не будут очищены в OnIdle () - в Visual C ++ 2008 этого не происходит.

Отладка приложения, содержащего ваш код, показывает, что во временной карте HWND в версии VC 10 гораздо больше объектов, чем в версии VC 9.

Код карты дескриптора (winhand.cpp), по-видимому, не изменился между двумя версиями, но в MFC есть много кода, который его использует!

Во всяком случае, если вы действительно хотите запустить свою программу следующим образом - я полагаю, вы работаете в каком-то автоматическом режиме? - тогда вы захотите форсировать сборку мусора через соответствующие промежутки времени. Посмотрите на эту запись в MSDN:

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

CWinThread :: OnIdle () фактически вызывает это, чтобы привести в порядок вещи:

AfxLockTempMaps();
AfxUnlockTempMaps(/*TRUE*/);
...