Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people, just like you, are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
Solved

Multithreading problems

Posted on 2001-09-01
13
1,005 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
Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
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
 
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

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
How to match SAS datasets by multiple key variables and then rename and create new variables? 2 97
Expand data scrubbing tool 13 35
only14 challenge 19 81
haveThree challenge 22 121
Introduction: Displaying information on the statusbar.   Continuing from the third article about sudoku.   Open the project in visual studio. Status bar – let’s display the timestamp there.  We need to get the timestamp from the document s…
Introduction: Dialogs (2) modeless dialog and a worker thread.  Handling data shared between threads.  Recursive functions. Continuing from the tenth article about sudoku.   Last article we worked with a modal dialog to help maintain informat…
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.

840 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