Access violation only in release build with debug info
-
Hi, I've SDI application with this code in CMainFrame::OnCreate() (only snippet) __m_wndDiscBar1.CreateEx(this, TBSTYLE_WRAPABLE|TBSTYLE_FLAT | TBSTYLE_TOOLTIPS |TBSTYLE_LIST, WS_CHILD | WS_VISIBLE | CBRS_ALIGN_TOP | CBRS_TOOLTIPS|CBRS_SIZE_DYNAMIC,CRect(0,0,0,0)); __m_wndDiscBar1.type=1; __m_wndDiscBar1.Update(false); __m_wndDiscBar1.SetFont(getFontLW()); __m_wndDiscBar2.CreateEx(this, TBSTYLE_WRAPABLE|TBSTYLE_FLAT | TBSTYLE_TOOLTIPS |TBSTYLE_LIST, WS_CHILD | WS_VISIBLE | CBRS_ALIGN_TOP | CBRS_TOOLTIPS | CBRS_SIZE_DYNAMIC,CRect(0,0,0,0)); __m_wndDiscBar2.type=2; __m_wndDiscBar2.Update(false); __m_wndDiscBar2.SetFont(getFontLW()); __m_wndDoubleDiscBar.Create(this,0); __m_wndDoubleDiscBar.ModifyStyle(0,CBRS_ALIGN_LEFT); __m_wndDoubleDiscBar.AddBar(&m_wndDiscBar2,NULL,NULL,RBBS_NOGRIPPER|RBBS_FIXEDS IZE); __m_wndDoubleDiscBar.AddBar(&m_wndDiscBar1,NULL,NULL,RBBS_NOGRIPPER|RBBS_FIXEDS IZE); m_wndDiscBar1/2 are classes derived from CToolBar. m_wndDoubleDiscBar is CReBar instance. Problem is in this function, which is called from CMyView::OnSize() (I have two CListViews divided by splitter) CMainFrame::ChangeDlgBar(int cx, int dx) { __CReBarCtrl& RCtrl = m_wndDoubleDiscBar.GetReBarCtrl(); __REBARBANDINFO rb; __rb.cbSize=sizeof(REBARBANDINFO); __// THIS IS PROBLEM FUNCTION __RCtrl.GetBandInfo(0,&rb); __rb.cx=width; __rb.wID=0; __rb.fMask=RBBIM_SIZE|RBBIM_ID; __rb.fStyle=RBBS_FIXEDSIZE|RBBS_NOGRIPPER; __RCtrl.SetBandInfo(0,&rb); __RCtrl.MinimizeBand(0); . . } Here is call stack: KERNEL32! 77ec8d34() KERNEL32! 77ec88f9() COMCTL32! 77b9e2d5() USER32! 77e3a244() USER32! 77e16b21() USER32! 77e16b44() CWnd:efWindowProcA(CWnd * const 0x004700a0 CHinfoFileView2::OnSize(unsigned int, int, int), unsigned int 1053, unsigned int 1, long 1239272) line 1006 + 19 bytes CWnd::WindowProc(CWnd * const 0x004700a0 CHinfoFileView2::OnSize(unsigned int, int, int), unsigned int 1053, unsigned int 1, long 1239272) line 1586 + 19 bytes CControlBar::WindowProc(CControlBar * const 0x004700a0 CHinfoFileView2::OnSize(unsigned int, int, int), unsigned int 1053, unsigned int 1, long 1239272) line 480 + 14 bytes CReBar::WindowProc(CReBar * const 0x004700a0 CHinfoFileView2::OnSize(unsigned int, int, int), unsigned int 1053, unsigned int 1, long 1239272) line 321 + 14 bytes AfxCallWndProc(CWnd * 0x00000000 {CWnd hWnd=???}, HWND__ * 0x00230560, unsigned int 1053, unsigned int 1, long 1239272) line 218 AfxWndProc(HWND__ * 0x00230560, unsigned int 1053, unsigned int 1, long 1239272)
-
s_k wrote: __REBARBANDINFO rb; __rb.cbSize=sizeof(REBARBANDINFO); __// THIS IS PROBLEM FUNCTION __RCtrl.GetBandInfo(0,&rb); try _REBARBANDINFO rb; ::ZeroMemory(&rb, sizeof(REBARBANDINFO)); __rb.cbSize=sizeof(REBARBANDINFO);
IT WORKS!! I thank you so much! Anyway, if you answered me this question, I would be even more happy: How is it possible that neither in debug version nor in release version without debug info no access violation appeared? Maybe I would understand difference between debug and clean release version, but what the heck is difference between, we can say, two DEBUG versions? Thank you again, AlexO, I really appreciate your help!
-
Hi, I've SDI application with this code in CMainFrame::OnCreate() (only snippet) __m_wndDiscBar1.CreateEx(this, TBSTYLE_WRAPABLE|TBSTYLE_FLAT | TBSTYLE_TOOLTIPS |TBSTYLE_LIST, WS_CHILD | WS_VISIBLE | CBRS_ALIGN_TOP | CBRS_TOOLTIPS|CBRS_SIZE_DYNAMIC,CRect(0,0,0,0)); __m_wndDiscBar1.type=1; __m_wndDiscBar1.Update(false); __m_wndDiscBar1.SetFont(getFontLW()); __m_wndDiscBar2.CreateEx(this, TBSTYLE_WRAPABLE|TBSTYLE_FLAT | TBSTYLE_TOOLTIPS |TBSTYLE_LIST, WS_CHILD | WS_VISIBLE | CBRS_ALIGN_TOP | CBRS_TOOLTIPS | CBRS_SIZE_DYNAMIC,CRect(0,0,0,0)); __m_wndDiscBar2.type=2; __m_wndDiscBar2.Update(false); __m_wndDiscBar2.SetFont(getFontLW()); __m_wndDoubleDiscBar.Create(this,0); __m_wndDoubleDiscBar.ModifyStyle(0,CBRS_ALIGN_LEFT); __m_wndDoubleDiscBar.AddBar(&m_wndDiscBar2,NULL,NULL,RBBS_NOGRIPPER|RBBS_FIXEDS IZE); __m_wndDoubleDiscBar.AddBar(&m_wndDiscBar1,NULL,NULL,RBBS_NOGRIPPER|RBBS_FIXEDS IZE); m_wndDiscBar1/2 are classes derived from CToolBar. m_wndDoubleDiscBar is CReBar instance. Problem is in this function, which is called from CMyView::OnSize() (I have two CListViews divided by splitter) CMainFrame::ChangeDlgBar(int cx, int dx) { __CReBarCtrl& RCtrl = m_wndDoubleDiscBar.GetReBarCtrl(); __REBARBANDINFO rb; __rb.cbSize=sizeof(REBARBANDINFO); __// THIS IS PROBLEM FUNCTION __RCtrl.GetBandInfo(0,&rb); __rb.cx=width; __rb.wID=0; __rb.fMask=RBBIM_SIZE|RBBIM_ID; __rb.fStyle=RBBS_FIXEDSIZE|RBBS_NOGRIPPER; __RCtrl.SetBandInfo(0,&rb); __RCtrl.MinimizeBand(0); . . } Here is call stack: KERNEL32! 77ec8d34() KERNEL32! 77ec88f9() COMCTL32! 77b9e2d5() USER32! 77e3a244() USER32! 77e16b21() USER32! 77e16b44() CWnd:efWindowProcA(CWnd * const 0x004700a0 CHinfoFileView2::OnSize(unsigned int, int, int), unsigned int 1053, unsigned int 1, long 1239272) line 1006 + 19 bytes CWnd::WindowProc(CWnd * const 0x004700a0 CHinfoFileView2::OnSize(unsigned int, int, int), unsigned int 1053, unsigned int 1, long 1239272) line 1586 + 19 bytes CControlBar::WindowProc(CControlBar * const 0x004700a0 CHinfoFileView2::OnSize(unsigned int, int, int), unsigned int 1053, unsigned int 1, long 1239272) line 480 + 14 bytes CReBar::WindowProc(CReBar * const 0x004700a0 CHinfoFileView2::OnSize(unsigned int, int, int), unsigned int 1053, unsigned int 1, long 1239272) line 321 + 14 bytes AfxCallWndProc(CWnd * 0x00000000 {CWnd hWnd=???}, HWND__ * 0x00230560, unsigned int 1053, unsigned int 1, long 1239272) line 218 AfxWndProc(HWND__ * 0x00230560, unsigned int 1053, unsigned int 1, long 1239272)
A few things I'd try: 1) Always test functions succeed. In particular CreateEx(), Create() etc. 2) In CMainFrame::ChangeDlgBar() add: ASSERT_VALID( this ); ASSERT( ::IsWindow( m_hWnd ); ASSERT( ::IsWindow( m_wndDoubleDiscBar.m_hWnd ) ); __CReBarCtrl& RCtrl = m_wndDoubleDiscBar.GetReBarCtrl(); ASSERT_VALID( &RCtrl ); ASSERT( ::IsWindow( RCtrl.m_hWnd ); Neville Franks, Author of ED for Windows. Free Trial at www.getsoft.com
-
A few things I'd try: 1) Always test functions succeed. In particular CreateEx(), Create() etc. 2) In CMainFrame::ChangeDlgBar() add: ASSERT_VALID( this ); ASSERT( ::IsWindow( m_hWnd ); ASSERT( ::IsWindow( m_wndDoubleDiscBar.m_hWnd ) ); __CReBarCtrl& RCtrl = m_wndDoubleDiscBar.GetReBarCtrl(); ASSERT_VALID( &RCtrl ); ASSERT( ::IsWindow( RCtrl.m_hWnd ); Neville Franks, Author of ED for Windows. Free Trial at www.getsoft.com
-
Thanks Neville! Fortunately, AlexO has already found the cause of the problem - I have to call ::ZeroMemory to zero REBARBANDINFO structure. Never thought this may be reason for CWnd::FromHandlePermanent() to return NULL...
Yes I saw Alex's post just after I sent mine. Initialization issues like this can be hard to track down and the outcome can vary depend on what crap happens to be being set. Bottom line is your back in business. Neville Franks, Author of ED for Windows. Free Trial at www.getsoft.com
-
Thanks Neville! Fortunately, AlexO has already found the cause of the problem - I have to call ::ZeroMemory to zero REBARBANDINFO structure. Never thought this may be reason for CWnd::FromHandlePermanent() to return NULL...
In debug mode build, the linker assigns bogus size storage for each block. When you accidentally forgotten to delete or deinitialize some component. The extra size storage in each other block can still cater as it had not touched the actual content. But once the linker had swicthed to release mode. All the storage blocks were optimise to it supposing size. When you have crossing action in your code, straight up a access violation will pop up. I read this in one of codeproject article. Can't remember the title already but hope this helps.
-
IT WORKS!! I thank you so much! Anyway, if you answered me this question, I would be even more happy: How is it possible that neither in debug version nor in release version without debug info no access violation appeared? Maybe I would understand difference between debug and clean release version, but what the heck is difference between, we can say, two DEBUG versions? Thank you again, AlexO, I really appreciate your help!
It is very common error in debug vs. release. The problem is debug memory allocation it usually initializes memory to 0 or 0xcdcdcdcd. Release memory is not initialized so values are random. Example: DWORD dwSize; //not that is not initialized SomeFunction(&dwSize);//note dwSize is in/out parameter the example above might work in debug but will blow up in release.
-
It is very common error in debug vs. release. The problem is debug memory allocation it usually initializes memory to 0 or 0xcdcdcdcd. Release memory is not initialized so values are random. Example: DWORD dwSize; //not that is not initialized SomeFunction(&dwSize);//note dwSize is in/out parameter the example above might work in debug but will blow up in release.
I don't understand. dwSize is just local variable. Its address (as passed to SomeFunction()) will be always valid, won't be? Of course SomeFunction() mustn't do something like this: TCHAR* s = new TCHAR[dwSize]; because dwSize was not initialized, but the code you posted itself is valid as long as I don't know SomeFunction() code...
-
I don't understand. dwSize is just local variable. Its address (as passed to SomeFunction()) will be always valid, won't be? Of course SomeFunction() mustn't do something like this: TCHAR* s = new TCHAR[dwSize]; because dwSize was not initialized, but the code you posted itself is valid as long as I don't know SomeFunction() code...
no, I did not mean address. Imagine that inside that function you have soemthing like int SomeFunction(DWORD* dwSize, char* actualBuffer) { if(*dwSize > 0) { char* pCopy = new char[*dwSize]; ::memcpy(pCopy, actualBuffer, *dwSize);//this is where error will manifest itself if you forgot to initialize dwSize, in release dwSize could be anything, in debug it would probably be zero so we never come here ... } ... } P.S. Real scenario is usually more complex but idea is the same
-
no, I did not mean address. Imagine that inside that function you have soemthing like int SomeFunction(DWORD* dwSize, char* actualBuffer) { if(*dwSize > 0) { char* pCopy = new char[*dwSize]; ::memcpy(pCopy, actualBuffer, *dwSize);//this is where error will manifest itself if you forgot to initialize dwSize, in release dwSize could be anything, in debug it would probably be zero so we never come here ... } ... } P.S. Real scenario is usually more complex but idea is the same