Professional UI Solutions
Site Map   /  Register
 
 

Forum

Please Log In to post a new message or reply to an existing one. If you are not registered, please register.

NOTE: Some forums may be read-only if you are not currently subscribed to our technical support services.

Forums » Prof-UIS Tech Support » Crash when open and closing MDI views fast Collapse All
Subject Author Date
Offer Har Apr 7, 2009 - 9:14 AM

Dear Support,


We have an MDI application, teh QA found a bug in it, that if they open many views, and then close them very fast, until they are all closed, and repeat that operation several times, the application crashed.


I was able to reproduce it in our application very easily, but not in the MDI sample application. However, it seems very Prof-UIS related, so I post here the stack. Can you please take a look and tell me how I can prevent it, or what is the source of the problem?


The assertion we get in the trace window is this:


 



Second Chance Assertion Failed: File f:\sp\vctools\vc7libs\ship\atlmfc\src\mfc\wingdi.cpp, Line 716



Many thanks,


Ron.


     ntdll.dll!7c90120e()    

     [Frames below may be incorrect and/or missing, no symbols loaded for ntdll.dll]   

>    msvcr80d.dll!_CrtDbgBreak()  Line 89    C

     msvcr80d.dll!_VCrtDbgReportA(int nRptType=2, const char * szFile=0x781df018, int nLine=716, const char * szModule=0x00000000, const char * szFormat=0x00000000, char * arglist=0x001251e4)  Line 290    C

     msvcr80d.dll!_CrtDbgReportV(int nRptType=2, const char * szFile=0x781df018, int nLine=716, const char * szModule=0x00000000, const char * szFormat=0x00000000, char * arglist=0x001251e4)  Line 300 + 0x1d bytes    C

     msvcr80d.dll!_CrtDbgReport(int nRptType=2, const char * szFile=0x781df018, int nLine=716, const char * szModule=0x00000000, const char * szFormat=0x00000000, ...)  Line 317 + 0x1d bytes    C

     mfc80d.dll!AfxAssertFailedLine(const char * lpszFileName=0x781df018, int nLine=716)  Line 25 + 0x14 bytes    C++

     mfc80d.dll!CDC::SetLayout(unsigned long dwSetLayout=0)  Line 716 + 0x18 bytes    C++

     ProfUIS284md.dll!CExtMemoryDC::__InitMemoryDC(CDC * pDC=0x00125338, const CRect * pRect=0x00125354, unsigned long dwOptFlags=3)  Line 97    C++

     ProfUIS284md.dll!CExtMemoryDC::CExtMemoryDC(CDC * pDC=0x00125338, const CRect * pRect=0x00125354, unsigned long dwOptFlags=3)  Line 222    C++

     ProfUIS284md.dll!CExtMiniDockFrameWnd::OnNcPaint()  Line 1195 + 0x15 bytes    C++

     mfc80d.dll!CWnd::OnWndMsg(unsigned int message=133, unsigned int wParam=0, long lParam=0, long * pResult=0x001254dc)  Line 2028    C++

     mfc80d.dll!CWnd::WindowProc(unsigned int message=133, unsigned int wParam=0, long lParam=0)  Line 1741 + 0x20 bytes    C++

     ProfUIS284md.dll!CExtMiniDockFrameWnd::WindowProc(unsigned int message=133, unsigned int wParam=0, long lParam=0)  Line 2357 + 0x14 bytes    C++

     mfc80d.dll!AfxCallWndProc(CWnd * pWnd=0x09fc13f0, HWND__ * hWnd=0x0007199a, unsigned int nMsg=133, unsigned int wParam=0, long lParam=0)  Line 240 + 0x1c bytes    C++

     mfc80d.dll!AfxWndProc(HWND__ * hWnd=0x0007199a, unsigned int nMsg=133, unsigned int wParam=0, long lParam=0)  Line 389    C++

     mfc80d.dll!AfxWndProcBase(HWND__ * hWnd=0x0007199a, unsigned int nMsg=133, unsigned int wParam=0, long lParam=0)  Line 411 + 0x15 bytes    C++

     user32.dll!7e418734()    

     user32.dll!7e42bdf1()    

     user32.dll!7e428ea0()    

     user32.dll!7e428eec()    

     ntdll.dll!7c90e453()    

     user32.dll!7e4194be()    

     user32.dll!7e42c174()    

     user32.dll!7e42f40b()    

     mfc80d.dll!CWnd::SendMessageA(unsigned int message=133, unsigned int wParam=0, long lParam=0)  Line 42 + 0x42 bytes    C++

     ProfUIS284md.dll!CExtMiniDockFrameWnd::OnNcActivate(int bActive=0)  Line 1472    C++

     mfc80d.dll!CWnd::OnWndMsg(unsigned int message=134, unsigned int wParam=0, long lParam=0, long * pResult=0x00125900)  Line 1890 + 0xd bytes    C++

     mfc80d.dll!CWnd::WindowProc(unsigned int message=134, unsigned int wParam=0, long lParam=0)  Line 1741 + 0x20 bytes    C++

     ProfUIS284md.dll!CExtMiniDockFrameWnd::WindowProc(unsigned int message=134, unsigned int wParam=0, long lParam=0)  Line 2357 + 0x14 bytes    C++

     mfc80d.dll!AfxCallWndProc(CWnd * pWnd=0x09fc13f0, HWND__ * hWnd=0x0007199a, unsigned int nMsg=134, unsigned int wParam=0, long lParam=0)  Line 240 + 0x1c bytes    C++

     mfc80d.dll!AfxWndProc(HWND__ * hWnd=0x0007199a, unsigned int nMsg=134, unsigned int wParam=0, long lParam=0)  Line 389    C++

     mfc80d.dll!AfxWndProcBase(HWND__ * hWnd=0x0007199a, unsigned int nMsg=134, unsigned int wParam=0, long lParam=0)  Line 411 + 0x15 bytes    C++

     user32.dll!7e418734()    

     user32.dll!7e418816()    

     user32.dll!7e428ea0()    

     user32.dll!7e428eec()    

     ntdll.dll!7c90e453()    

     user32.dll!7e4194be()    

     user32.dll!7e42c174()    

     user32.dll!7e42f40b()    

     mfc80d.dll!CWnd::SendMessageA(unsigned int message=134, unsigned int wParam=0, long lParam=0)  Line 42 + 0x42 bytes    C++

     mfc80d.dll!CMiniFrameWnd::OnFloatStatus(unsigned int wParam=8, long __formal=0)  Line 224    C++

     mfc80d.dll!CWnd::OnWndMsg(unsigned int message=877, unsigned int wParam=8, long lParam=0, long * pResult=0x00125d20)  Line 2004 + 0x11 bytes    C++

     mfc80d.dll!CWnd::WindowProc(unsigned int message=877, unsigned int wParam=8, long lParam=0)  Line 1741 + 0x20 bytes    C++

     ProfUIS284md.dll!CExtMiniDockFrameWnd::WindowProc(unsigned int message=877, unsigned int wParam=8, long lParam=0)  Line 2357 + 0x14 bytes    C++

     mfc80d.dll!AfxCallWndProc(CWnd * pWnd=0x09fc13f0, HWND__ * hWnd=0x0007199a, unsigned int nMsg=877, unsigned int wParam=8, long lParam=0)  Line 240 + 0x1c bytes    C++

     mfc80d.dll!AfxWndProc(HWND__ * hWnd=0x0007199a, unsigned int nMsg=877, unsigned int wParam=8, long lParam=0)  Line 389    C++

     mfc80d.dll!AfxWndProcBase(HWND__ * hWnd=0x0007199a, unsigned int nMsg=877, unsigned int wParam=8, long lParam=0)  Line 411 + 0x15 bytes    C++

     user32.dll!7e418734()    

     user32.dll!7e418816()    

     user32.dll!7e428ea0()    

     user32.dll!7e428eec()    

     ntdll.dll!7c90e453()    

     user32.dll!7e4194be()    

     user32.dll!7e42c174()    

     user32.dll!7e42f40b()    

     mfc80d.dll!CFrameWnd::NotifyFloatingWindows(unsigned long dwFlags=8)  Line 515    C++

     mfc80d.dll!CFrameWnd::OnActivate(unsigned int nState=0, CWnd * pWndOther=0x09fd5d98, int bMinimized=0)  Line 985    C++

     mfc80d.dll!CWnd::OnWndMsg(unsigned int message=6, unsigned int wParam=0, long lParam=858492, long * pResult=0x00126170)  Line 2105    C++

     mfc80d.dll!CWnd::WindowProc(unsigned int message=6, unsigned int wParam=0, long lParam=858492)  Line 1741 + 0x20 bytes    C++

     mfc80d.dll!AfxCallWndProc(CWnd * pWnd=0x08f85408, HWND__ * hWnd=0x001915b6, unsigned int nMsg=6, unsigned int wParam=0, long lParam=858492)  Line 240 + 0x1c bytes    C++

     mfc80d.dll!AfxWndProc(HWND__ * hWnd=0x001915b6, unsigned int nMsg=6, unsigned int wParam=0, long lParam=858492)  Line 389    C++

     mfc80d.dll!AfxWndProcBase(HWND__ * hWnd=0x001915b6, unsigned int nMsg=6, unsigned int wParam=0, long lParam=858492)  Line 411 + 0x15 bytes    C++

     user32.dll!7e418734()    

     user32.dll!7e418816()    

     user32.dll!7e42a013()    

     user32.dll!7e42a998()    

     ProfUIS284md.dll!CExtHookSink::HookChains_t::HookChainsWindowProc(unsigned int nMessage=6, unsigned int & wParam=0, long & lParam=858492)  Line 227 + 0x20 bytes    C++

     ProfUIS284md.dll!CExtHookSink::HookChains_t::g_HookWndProc(HWND__ * hWnd=0x001915b6, unsigned int nMessage=6, unsigned int wParam=0, long lParam=858492)  Line 291 + 0x14 bytes    C++

     user32.dll!7e418734()    

     user32.dll!7e418816()    

     user32.dll!7e428ea0()    

     user32.dll!7e428eec()    

     ntdll.dll!7c90e453()    

     user32.dll!7e42b11e()    

     user32.dll!7e43ada0()    

     user32.dll!7e418734()    

     user32.dll!7e42413c()    

     user32.dll!7e423b30()    

     user32.dll!7e43e577()    

     mfc80d.dll!CThreadSlotData::GetThreadValue(int nSlot=0)  Line 265    C++

     user32.dll!7e43e599()    

     user32.dll!7e418734()    

     user32.dll!7e43e577()    

     user32.dll!7e43e577()    

     user32.dll!7e418816()    

     user32.dll!7e43e577()    

     user32.dll!7e43e577()    

     user32.dll!7e418b26()    

     user32.dll!7e42a013()    

     user32.dll!7e43e577()    

     user32.dll!7e42a998()    

     user32.dll!7e43e577()    

     mfc80d.dll!_AfxActivationWndProc(HWND__ * hWnd=0x0012675c, unsigned int nMsg=1206372, unsigned int wParam=2017153533, long lParam=0)  Line 425 + 0x1a bytes    C++

     user32.dll!7e43e577()    

     user32.dll!7e418734()    

     user32.dll!7e418816()    

     user32.dll!7e428ea0()    

     user32.dll!7e428eec()    

     ntdll.dll!7c90e453()    

     user32.dll!7e4194be()    

     user32.dll!7e42c174()    

     user32.dll!7e42651a()    

     user32.dll!7e42b372()    

Technical Support Apr 8, 2009 - 6:43 AM

Please use on stack local GDI objects:

CDC & dc = . . .
CPen pen( . . . );
CPen * pOldPen = dc.SelectObject( &pen );
            . . .
            dc.SelectObject( pOldPen );
Then carefully check everything is restored (old GDI objects are selected finally). It’s a good style to restore selected objects in the exactly inversive order. Please do not invoke C++ operators like return, break or throw if they can affect to non restored GDI handles.
If you are using GDI handles like HBRUSH, HPEN, HGDIOBJ instead of MFC wrapper classes, then please check their usage even more carefully. Such handles are used in the same way as their MFC wrapper classes, but you should not forget to destroy them using the ::DeleteObject() Win32 API. The HICON handles must be destroyed using the ::DestroyIcon() Win32 API - not the ::DeleteObject() API.
The HBITMAP handles are assumed as heavy GDI resources. Do not cache too much HBITMAP / CBitmap objects. Switching to the CExtBitmap objects allows you to allocate zero count of HBITMAP handles in your application. You can cache any number of CExtBitmap objects in your application. The HICON handles are typically eating more than one GDI handle. The CExtBitmap class can replace HICON handle because our bitmap supports alpha blending on any Windows OS. To draw CExtBitmap images you can use the CExtBitmap::Draw() or CExtBitmap::AlphaBlend() methods.

Technical Support Apr 7, 2009 - 1:01 PM

Here is the source code of the CDC::SetLayout() method where the assertion is occurred:

DWORD CDC::SetLayout(DWORD dwSetLayout)
{
            ASSERT(m_hDC != NULL);

            HINSTANCE hInst = ::GetModuleHandleA("GDI32.DLL");
            ASSERT(hInst != NULL);

            DWORD dwGetLayout = LAYOUT_LTR;

            AFX_GDISETLAYOUTPROC pfn;
            pfn = (AFX_GDISETLAYOUTPROC) GetProcAddress(hInst, "SetLayout");

            // If the API is availalbe, just call it. If it’s not available,
            // setting anything other than LAYOUT_LTR is an error.

            if (pfn != NULL)
                        dwGetLayout = (*pfn)(m_hDC, dwSetLayout);
            else if (dwSetLayout != LAYOUT_LTR)
            {
                        dwGetLayout = GDI_ERROR;
                        SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
            }

            return dwGetLayout;
}

We suspect the assertion line is the ASSERT(m_hDC != NULL); code. This means the memory based HDC handle was not created successfully inside the CExtMemoryDC class. So, this means it’s time to check the GDI handle leaks. The number of total GDI handles on NT systems is limited to 10000. If this limit is reached then all the font handles become referred to the System proportional font, most of bitmaps and icons are not painted on the screen, etc. But the HDC handles become not created successfully even at lower limit of GDI handles. Please run your application, open the Windows Task Manager, select the Processes tab page in it, make it displaying the Handles, Threads, User Objects and GDI Objects columns, select you application in the process list and try to take a look at the handle counts when you opening new MDI child frame windows and closing them. The numbers of handles may increase after you several times open/close particular MDI child frames, but finally, all the handle counts should become persistent. This means you will open and close MDI child frames and each time return to some check point state of your application, probably, with no MDI child frames opened at all. At this check point, the number of handles should be persistent.

Please provide us with some details about the view windows inside MDI child frames in your application. Do you use something painted from scratch? If yes, then please do not cache any GDI handles. Do not cache the bitmap handles, we have the CExtBitmap class for that and it’s handle less and fast. Do not cache pens, brushes, and, especially, HDC handles. This means your classes should not have properties like CDC m_DC; or CBrush m_brush;.

Offer Har Apr 7, 2009 - 1:30 PM

Dear Support,


Thank you very much for your detailed explanation - it was a GDI resources leak! it crashed at 10,000 exactly...


One question - say I have a solid black line pen, how will a go to implement it if I will not have  a member of type CPen in my class?


Thanks,


Ron.