Solved

Multithreading problems

Posted on 2001-09-01
13
992 Views
Last Modified: 2013-11-20
Hi,

there is a problem which I cannot solve so far. In an SDI application I need to send a message from a working thread to the main frame window. In debug version all works fine, but in release version "access violation" happens.

I creating new working thread wih AfxBeginThread() and HWND of main frame is being passed to new thread as a parameter, it waiting for some events and then sending a message to main frame. And in release version when one of these events happens and thread sends message to main frame, unclear things occurs. I builded release version with debug info, and it seems that somewhere in MFC (in threadcore.cpp and wincore.cpp) some mess with HWND happens during translating messages.

This is how stack looking at the moment of error (and what is interesting message 867 (WM_IDLEUPDATECMDUI) is not the message that working thread sending to main frame):
===========================================================
CWnd::AttachControlSite(CWnd * const 0x017b0364 {CMapPtrToPtr}, CHandleMap * 0x017b0360) line 420

CWnd::FromHandle(HWND__ * 0x00000cd8) line 293

CWnd::GetOwner(const CWnd * const 0x017b0364 {CMapPtrToPtr}) line 35 + 22 bytes

CControlBar::OnIdleUpdateCmdUI(CControlBar * const 0x017b0364 {CMapPtrToPtr}, unsigned int 1, long 0) line 687 + 7 bytes

CWnd::OnWndMsg(CWnd * const 0x017b0364 {CMapPtrToPtr}, unsigned int 867, unsigned int 1, long 4677952, long * 0x0073fc54) line 1982 + 8 bytes

CWnd::WindowProc(CWnd * const 0x017b0364 {CMapPtrToPtr}, unsigned int 867, unsigned int 1, long 0) line 1585 + 27 bytes

CControlBar::WindowProc(CControlBar * const 0x017b0364 {CMapPtrToPtr}, unsigned int 867, unsigned int 1, long 0) line 480 + 14 bytes

AfxCallWndProc(CWnd * 0x00000000 {CWnd hWnd=???}, HWND__ * 0x00000ee0, unsigned int 867, unsigned int 1, long 0) line 218

//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//CURIOUS MOMENT
//the function CWnd::SendMessageToDescendants() calls
//AfxCallWndProc() in such a way:
//
//  if (pWnd != NULL)
//  {
//    AfxCallWndProc(pWnd, pWnd->m_hWnd, message, wParam, lParam);
//  }
//
//In other words CWnd* in AfxCallWndProc cannot be NULL,
//but we see the opposite
//

CWnd::SendMessageToDescendants(HWND__ * 0x00000cd8, unsigned int 867, unsigned int 1, long 0, int 1, int 1) line 2309

CWnd::SendMessageToDescendants(HWND__ * 0x00000fc8, unsigned int 867, unsigned int 1, long 0, int 1, int 1) line 2318 + 21 bytes

CWinThread::OnIdle(CWinThread * const 0x017b0364 {CMapPtrToPtr}, long 4507474) line 551

CWinApp::OnIdle(CWinApp * const 0x017b0364 {CMapPtrToPtr}, long 0) line 480

CWinThread::Run(CWinThread * const 0x017b0364 {CMapPtrToPtr}) line 472 + 16 bytes

CWinApp::Run(CWinApp * const 0x017b0364 {CMapPtrToPtr}) line 399 + 7 bytes

AfxWinMain(HINSTANCE__ * 0x00400000, HINSTANCE__ * 0x00000000, char * 0x801adfa2, int 1) line 49 + 7 bytes

WinMain(HINSTANCE__ * 0x00400000, HINSTANCE__ * 0x00000000, char * 0x801adfa2, int 1) line 30

MYAPPLICATION! WinMainCRTStartup + 224 bytes
===========================================================

This is piece of code where exception is being throwed:
===========================================================
void CWnd::AttachControlSite(CHandleMap* pMap)
{
  if (this != NULL && m_pCtrlSite == NULL)
  {
    // Determine if parent is an OLE control container
    CWnd* pWndParent = (CWnd*)pMap->LookupPermanent
            (::GetParent(m_hWnd));

    if (pWndParent != NULL && pWndParent->m_pCtrlCont
           != NULL)
    {

// delegate through helper in COleControlSite
exception here
===>>  pWndParent->m_pCtrlCont->AttachControlSite(this);
    }
  }
}
===========================================================

This is how "this" looking at the moment of error:
===========================================================
-      this      0x017b0364 {CMapPtrToPtr}
+      [CMapPtrToPtr]      {CMapPtrToPtr}
+      CCmdTarget      {CCmdTarget}
+      classCWnd      {"CWnd"}
+      m_hWnd      0x0047760c const  CMapPtrToPtr::`vftable'
+      wndTop      {CWnd hWnd=0x00000000}
+      wndBottom      {CWnd hWnd=0x00000001}
+      wndTopMost      {CWnd hWnd=0xffffffff}
+      wndNoTopMost      {CWnd hWnd=0xfffffffe}
+      m_hWndOwner      0x00000000
      m_nFlags      7
      m_pfnSuper      0x00000000
      m_nMsgDragList      51462
      m_nModalResult      0
+      m_pDropTarget      0x00000000 {COleDropTarget}
+      m_pCtrlCont      0x00000004 {COleControlContainer}
+      m_pCtrlSite      0x00472ec8 {CMapPtrToPtr}
+      _messageEntries      0x00472f18
+      messageMap      {...}    
===========================================================


Can someone to shed some light upon that problem?
0
Comment
Question by:mnbmnb
  • 4
  • 3
  • 2
  • +4
13 Comments
 
LVL 32

Expert Comment

by:jhance
ID: 6448687
>>In debug version all works fine, but in release
>>version "access violation" happens.

Any time I hear this it boils down to the same problem.  You are overwriting one or more memory locations in your program.  The DEBUG build pads memory allocation and fills them with a pattern so as to detect when adjacent memory locations get overwritten.  The RELEASE build doesn't do this.

The simplest way to find this is to run the DEBUG build in the DEBUGGER.  You'll get a warning when the problem happens as the DEBUG runtime libraries detect the memory overwrite problem.
0
 

Author Comment

by:mnbmnb
ID: 6448734
>>In debug version all works fine, but in release
>>version "access violation" happens.

>Any time I hear this it boils down to the same problem.  

Well, it seems that when you read this two strings, you did not read any further. Access violation in my case happens not because of memory overwriting, but because of that there is try of operation with zero object.
0
 
LVL 32

Expert Comment

by:jhance
ID: 6448750
Well, I guess it's clear that you have this solved....
0
 
LVL 9

Expert Comment

by:ShaunWilde
ID: 6448939
are you sending or posting? MFC CWnd objects are not thread safe due to all the message maps - however I'd have expected it to crash in debug to is this was the case.

If it is not necessary to do a sendmessage then try postmessage and use plain SDK (since you have the HWND) so you don't create any superflous MFC objects


eg if your sendmessage was like this

CMyDataObject obj;
SendMessage(hWnd,MM_SENDDATAOBJECT,0,&obj);

then change it to

CMyDataObject *pobj=new CMyDataObject; // delete in message handler
PostMessage(hWnd,MM_SENDDATAOBJECT,0,pobj);

0
 

Author Comment

by:mnbmnb
ID: 6449021
ShaunWilde:

I posting and I even do not passing with message any pointer. Only message with lParam and wParam as zeroes. I tryed to change the receiver of message from the main frame to view, but effect is the same: after handling my message program crashed because of in CWnd class member m_pCtrlSite which was zero before handling my message appears some garbage and CWnd's functions begin trying to access this member as follows:

CWnd* CWnd::SetFocus()
{
     ASSERT(::IsWindow(m_hWnd));

     if (m_pCtrlSite == NULL)
          return CWnd::FromHandle(::SetFocus(m_hWnd));
     else
          return m_pCtrlSite->SetFocus();
}

Things seems like the CWnd object becomes corrupt after handling my message. And I have no idea why. The most interesting that in debug version I have no any warning and all works perfectly.
0
 

Author Comment

by:mnbmnb
ID: 6449030
It need not to say that handling of my message does not touch m_pCtrlSite in any way.
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 9

Expert Comment

by:ShaunWilde
ID: 6449901
what does your handler look like ?

map__________________________________prototype

ON_MESSAGE( <message>, <memberFxn> ) afx_msg LRESULT memberFxn(WPARAM, LPARAM);
ON_REGISTERED_MESSAGE( <nMessageVariable>, <memberFxn> ) afx_msg LRESULT memberFxn(WPARAM, LPARAM);
ON_THREAD_MESSAGE( <message>, <memberFxn> ) afx_msg void memberFxn( UINT, LONG );
ON_REGISTERED_THREAD_MESSAGE( <nMessageVariable>, <memberFxn> ) afx_msg void memberFxn( UINT, LONG );

0
 
LVL 9

Accepted Solution

by:
ShaunWilde earned 300 total points
ID: 6449903
a common mistake (debug work relase not) is to use the wrong map- prototype combination
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 6450076
I agree with Shaun.. check your message handlers.  When I had similar problems, it was because I had declared a handler with an improper number of arguments.  Debug version can mask that error.

Also -- just a thought-- the stack trace could be misleading because of the multithreaded aspect.  I'm not sure how, but maybe.

-- Dan
0
 

Expert Comment

by:aparna-learner
ID: 6450082
mnbmnb,
How are you implementing the thread class? That is, thc class it is derived from, the mode in which the thread is created and other details..Could you post the thread code (or relevant parts of it)?
0
 
LVL 2

Expert Comment

by:BogdyPtr
ID: 6450364
I tryed to pass the HWND of main window to a thread proc and send messagess to that window in a SDI app but it did not work. But if I passed the pointer to CMainFrame class to the proc that worked. Maybe u can find it usefull too. Below is the code that creates the thread and the thread proc.


UINT fnc( LPVOID pParam )
{
     Sleep( 2000 );
     ((CWnd*)pParam)->ShowWindow( SW_HIDE );
     Sleep( 2000 );
     ((CWnd*)pParam)->ShowWindow( SW_SHOW );
     return 0;
}

void CAaaView::OnButton1()
{
      //Creating the thread
     AfxBeginThread( fnc, AfxGetApp()->m_pMainWnd );    
}
0
 

Author Comment

by:mnbmnb
ID: 6450945
ShaunWilde:

Yes, it was wrong prototype. I had saw it myself, but thanks anyway.
0
 

Expert Comment

by:tjeutje
ID: 6450955
It might be useful to debug the release version. This seems like a contradiction, but it works: in Project settings, on the C/C++ tab (category General), in the Debug info combo box select anything but the default "none"; and on the Link tab (general category), check the "Generate debug info" box. This gives you an opportunity to step through your code (the compiled program will be slightly larger), while all initialization, memory allocation etc. is done like in a regular release version.
If your problem is caused by a message handler with the wrong no. of parameters, you'll get an error message after exiting that message handler.
0

Featured Post

Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

Join & Write a Comment

Suggested Solutions

In this article, I'll describe -- and show pictures of -- some of the significant additions that have been made available to programmers in the MFC Feature Pack for Visual C++ 2008.  These same feature are in the MFC libraries that come with Visual …
If you use Adobe Reader X it is possible you can't open OLE PDF documents in the standard. The reason is the 'save box mode' in adobe reader X. Many people think the protected Mode of adobe reader x is only to stop the write access. But this fe…
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
This tutorial demonstrates a quick way of adding group price to multiple Magento products.

758 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now