Toolbar Dialog verursacht Speicherleck [gelöst]
-
Ich habe in einem Dialog-Fenster eine Toolbar (ich nenn sie mal Haupt-Toolbar) eingebaut. Drückt man auf den ersten Knopf der Haupt-Toolbar geht ein zweiter Dialog auf, welche nur aus einer weiteren Toolbar besteht. Dieser schliesst sich automatisch sobald man außerhalb dieser Toolbar klickt.
Und genau dieser Toolbar-Dialog verursacht ein Speicherleck. Wenn ich den Dialog öffne, werden 8-20 KByte zusätzlichen Speicher reserviert. Dieser Speicher wird aber nicht freigegeben wenn der Dialog geschlossen wird. Das es ein Speicherleck ist scheint mit klar zu sein denn wenn ich den Toolbar-Dialog ständig öffne und schliesse, steigt die Speicheranforderung ohne Probleme um ein paar MByte.
Im Code mache ich folgendes:
LRESULT CALLBACK MainWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { ... case IDC_FIRST_TOOLBAR_BUTTON_CLICK: { if (hSecondToolbarDialog == NULL) hSecondToolbarDialog = CreateDialog(hModuleInstance, MAKEINTRESOURCE(IDD_SECONDTOOLBAR), hWnd, SecondToolbar_DialogProc); else { EndDialog(hSecondToolbarDialog, 0); hSecondToolbarDialog = NULL; } return 0 } ... } BOOL CALLBACK SecondToolbar_DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch(uMsg) { case WM_INITDIALOG: { TBADDBITMAP BitmapID; TBBUTTON tbButton; HWND hToolBar; RECT Rect; hToolBar = CreateWindowEx(0, TOOLBARCLASSNAME, NULL, WS_CHILD | WS_VISIBLE | TBSTYLE_FLAT | TBSTYLE_TRANSPARENT | TBSTYLE_TOOLTIPS | CCS_NODIVIDER, 0, 0, 0, 0, hwndDlg, (HMENU) 1, hModuleInstance, NULL); BitmapID.hInst = NULL; BitmapID.nID = (UINT_PTR) hFirstToolbarButtonBitmap; tbButton.iBitmap = SendMessage(hToolBar, TB_ADDBITMAP, 1, (LPARAM)(LPTBADDBITMAP) &BitmapID); tbButton.idCommand = IDC_FIRSTTOOLBARBUTTON; tbButton.fsState = TBSTATE_ENABLED; tbButton.fsStyle = 0; tbButton.dwData = 0; tbButton.iString = NULL; SendMessage(hToolBar, TB_ADDBUTTONS, (WPARAM) 1, (LPARAM) (LPTBBUTTON) &tbButton); // Hier werden noch weitere Toolbar Buttons eingefügt SendMessage(hToolBar, TB_SETROWS, MAKEWPARAM(1, TRUE), (LPARAM) &Rect); ShowWindow(hToolBar, SW_SHOW); // Positionierung der Toolbar return TRUE; } } return FALSE; }Debugging mittels crtdbg.h bringt keine Ergebnisse. DebugDiag bringt aber folgendes Ergebnis:
comctl32.dll is responsible for 365,46 KBytes worth of outstanding allocations. The following are the top 2 memory consuming functions: comctl32!operator new+10: 275,46 KBytes worth of outstanding allocations. comctl32!ToolbarWndProc+4f: 51,33 KBytes worth of outstanding allocations. ... Call stack sample 1 Address 0x0017ab18 Allocation Time 00:07:01 since tracking started Allocation Size 1,52 KBytes Function Source Destination comctl32!operator new+10 kernel32!LocalAlloc comctl32!CImageList::Create+4e comctl32!operator new comctl32!ImageList_CreateInstance+27 comctl32!CImageList::Create comctl32!ImageList_Create+22 comctl32!ImageList_CreateInstance comctl32!TBAddBitmapToImageList+36 comctl32!ImageList_Create comctl32!AddBitmap+a4 comctl32!TBAddBitmapToImageList comctl32!ToolbarWndProc+f63 comctl32!AddBitmap user32!InternalCallWinProc+28 user32!UserCallWinProcCheckWow+150 user32!InternalCallWinProc user32!SendMessageWorker+4a5 user32!UserCallWinProcCheckWow user32!InternalCreateDialog+9df user32!SendMessageWorker user32!CreateDialogIndirectParamAorW+33 user32!InternalCreateDialog user32!CreateDialogParamA+4a user32!CreateDialogIndirectParamAorW TestProjekt!MainWindowProc+14e4 c:\devel\TestProjekt\gui.cpp @ 1141 user32!CreateDialogParamA user32!InternalCallWinProc+28 user32!UserCallWinProcCheckWow+150 user32!InternalCallWinProc user32!SendMessageWorker+4a5 user32!UserCallWinProcCheckWow user32!SendMessageW+7f user32!SendMessageWorker comctl32!TBOnLButtonUp+122 user32!SendMessageW comctl32!ToolbarWndProc+b30 comctl32!TBOnLButtonUpDer Verweis gui.cpp @ 1141 zeigt genau auf den CreateDialog Befehl (also wohl in SecondToolbar_DialogProc auf WM_INITDIALOG). Und offenbar scheint die Toolbar sich hier eine Image Liste (mittels TB_ADDBITMAP) aufzubauen, diese aber nicht mehr freizugeben. Warum dies aber nicht nach dem Beenden des Dialog's freigegeben wird, verstehe ich nicht.

Was mache ich hier falsch ???

-
Ich bin blöd

Typischer Fall von Fehlerbehebung durch Fehlerbeschreibung.
Ich schliesse den Dialog mittels EndDialog() was man nach MSDN nicht machen sollte. Ersetze ich den Befehl durch DestroyWindow verschwindet das Speicherleck.