?
Solved

MFC First chance exception

Posted on 2009-02-09
16
Medium Priority
?
2,863 Views
Last Modified: 2013-11-20
hi experts,
I created a MFC dialog based application with VS2008.There is no error message when compiling but when debugging the debugger stops on the following "ALTASSERT()" inside the altsimpstr.h file at line 107:

void Release() throw()
{
ATLASSERT( nRefs != 0 ); // The debugger stops hier
if( _AtlInterlockedDecrement( &nRefs ) <= 0 )
{
   pStringMgr->Free( this );
}
}
the call stack dump at that point of crash is:
mfc90d.dll!ATL::CStringData::Release()  Line 107 + 0x3 bytes
mfc90d.dll!ATL::CSimpleStringT<wchar_t,1>::~CSimpleStringT<wchar_t,1>()  Line 279
mfc90d.dll!ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t> > >::~CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t> > >()  Line 1011 + 0x8 bytes
Test.exe!CTestDlg::~CTestDlg()  + 0x5a bytes
Test.exe!CTestApp::InitInstance()  Line 73 + 0x1c bytes
mfc90d.dll!AfxWinMain(HINSTANCE__ * hInstance=0x00400000, HINSTANCE__ * hPrevInstance=0x00000000, char * lpCmdLine=0x00151f17, int nCmdShow=0x00000001)  Line 37 + 0xd bytes
Test.exe!WinMain(HINSTANCE__ * hInstance=0x00400000, HINSTANCE__ * hPrevInstance=0x00000000, char * lpCmdLine=0x00151f17, int nCmdShow=0x00000001)  Line 30
Test.exe!__tmainCRTStartup()  Line 574 + 0x35 bytes
Test.exe!WinMainCRTStartup()  Line 399

The first chance exception is at 0x7861d8ec with an access violation at the reading location 0xfffffffc.
What does that mean?
Thank you
Andy
      
      
      
      
      
      

      
      

      
0
Comment
Question by:andy06
  • 5
  • 4
  • 4
  • +1
16 Comments
 
LVL 9

Expert Comment

by:Gurudenis
ID: 23589689
I'm afraid there's no simple answer. You need to debug thoroughly. Have you tried:
1) commenting parts of the code
2) stepping through the code
3) ensuring that CString members of CTestDlg are only destroyed once

Also, see these links (with a bit of luck, one of these may prove to be relevant):
1) http://www.codeproject.com/script/Forums/View.aspx?fid=1647&msg=2741873
2) http://social.microsoft.com/Forums/en-US/vcgeneral/thread/26100fab-e983-4da2-8afb-9f805567828c
3) http://www.codeguru.com/forum/archive/index.php/t-224686.html
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 23590024
>>>> The first chance exception is at 0x7861d8ec with an access violation at the reading location 0xfffffffc.
>>>> What does that mean?

Firstly, a first chance exception not necessarily is an error. It simply means that the workflow happened to jump into a catch block. So, when debugging you often will see first chance exceptions which simply means that the MFC makes some checks, e. g. on handles/pointers associated to a window, and in case of an exception it knows that the entry isn't valid any more.

Things were different if an assertion happens after first chance exception. That means the original error was catched by the first chance but could not be solved. Hence they made an assertion in order to break the program in debug mode.

>>>> The first chance exception is at 0x7861d8ec with an access violation at the reading location 0xfffffffc.

You best change your debug settings so that the debugger stops immediately for 'access violation'. Goto menu "Debug - Exceptions -  Win32 Exceptions - c0000005 Access violations" and specify to immediately break in the debugger when 'access violaton happens'. Then, the debugger would break immediately after access violation and you can examine the call stack to find out which function (of yours) passed or used the wrong/invalid CString (It is often tjhat you were using a CString though it already was deleted - or the class object where it was member of  was deleted or run out of scope).
 
0
 

Author Comment

by:andy06
ID: 23590709
thank you very much for the hints...
I'm running actually a multi-threaded apllication and in my Threadfunction I declared something like this:
UINT _cdecl  Threadfunction (LPVOID lpParam)
{
CTestDlg *pDlg =(CTestDlg *) lpParam;
CString csMessage, csformat;
TCHAR MyText[] = _T("Begin Test");
csFormat.Format(MyText);
pDlg-> m_Size.SetWindowText(csFormat);
//.....Code
...
}
where m_Size is the associated member variable  of an Edit Control where some results are beeing displayed.
The debugger breaks 2  lines after  the statement:
pDlg -> m_Size.SetWindowText(csFormat);
and by the value of csformat and csMessage one can read :<Bad Ptr>
I checked the whole code and  "csformat" has been used only once and at the time of crash csMessage hasn't been used ...
Thank you

0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
LVL 45

Expert Comment

by:AndyAinscow
ID: 23591150
MFC is NOT thread safe.  
You need to pass window handles not MFC objects between threads and then construct MFC objects and attach them to the supplied handle (or pass the information back to the MFC object and let that update the edit control).
0
 
LVL 9

Expert Comment

by:Gurudenis
ID: 23591342
>> pass the information back to the MFC object and let that update the edit control

This is usually the best way around. Consider something like:

static const MY_CUSTOM_MESSAGE = WM_APP + 123;

UINT _cdecl  Threadfunction (LPVOID lpParam)
{
    HWND dlg =(HWND) lpParam;
    CString csMessage, csformat;
    TCHAR MyText[] = _T("Begin Test");
    csFormat.Format(MyText);

    // Instead of pDlg-> m_Size.SetWindowText(csFormat), use:
    ::SendMessage(dlg,MY_CUSTOM_MESSAGE,(WPARAM)&csFormat,0);
   
    //.....Code
    ...
}

// To the dialog's message map, add:

ON_MESSAGE(MY_CUSTOM_MESSAGE, &CTestDlg::OnMyCustomMessage)

// Finally, handle that message like this:
LRESULT CTestDlg::OnMyCustomMessage(WPARAM wParam, LPARAM)
{
    CString* pS = (CString*)wParam;
    m_Size.SetWindowText(*pS)
    return 0;
}

0
 

Author Comment

by:andy06
ID: 23591369
AndyAinscow:
For example I know that to get the handle of the dialog window could be :
HWND m_hWnd= pDlg->GetSafeHwnd();
But what about the construction of MFC Objets which should be attached to the handle?I read about "Attach" but how could I use it to let my result appear in the Edit Control ?
0
 

Author Comment

by:andy06
ID: 23591584
I sent my last message before reading the last comment...
Isn't it better to use PostMessage instead of Sendmessage ...?
0
 
LVL 45

Expert Comment

by:AndyAinscow
ID: 23592143
PostMessage is better (SendMessage would force the thread to wait).
0
 
LVL 9

Expert Comment

by:Gurudenis
ID: 23592420
I used SendMessage to simplify memory management of the CString parameter. In the real code, PostMessage is of course preferable, although SendMessage will only really be undesirable in more complicated applications.
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 23592684
>>>> You need to pass window handles not MFC objects between threads
That is not so much a difference as long as the thread could not  life longer than the dialog ...  If you can't guarantee that you would need to overwrite CWnd::OnNCDestroyWindow (that is the last handler before your dialog window actually was destroyed) and force your thread to terminate there e. g.  

void CMyDialog::OnNCDestroyWindow()
{
      m_thread.setStopFlag();
      int count = 10;
      while (--count > 0 && m_thread.stopRecognized() == FALSE)
      {
             Sleep(100);   // 100 msec
      }
       if (count < 0) // not stopped
       {
             // force termination
             TerminateThread(m_thread.m_handle);
        }
}

The above requires a thread structure like

struct MyThread
{
     HANDLE        m_handle;       // thread handle
     CMyDialog*   m_ptrParent;  // parent dialog
     BOOL            m_isStopped;  // stop flag
     BOOL            m_stopRecognized;  // stop flag regognized
     
     MyThread(CMyDialog * ptrParent)
         : m_handle(NULL), m_ptrParent(ptrParent),
           m_isStopped(FALSE), m_stopRecognized(FALSE)
     {}
   
     BOOL   stopRecognized()  { return m_stopRecognized; }
     void     setStopFlag() { m_isStopped = TRUE; }
     void     setHandle(HANDLE hdl) { m_handle = hdl; }
};

where the instance was passed when the thread was created (instead of the this as it was now):

 CMyDialog::CMyDialog()
   : CDialog(CMyDialog::IDD),
     m_thread(this)
 {
     ....
 }

void CMyDialog::OnBtnClickedStartThread()
{
     ...
     HANDLE hdl = CreateThread(NULL, 0, CMyDialog::ThreadFunc, &m_thread, NULL, NULL);
     // the handle can be set afterwards
     m_thread.setHandle(hdl);
}

>>>> Isn't it better to use PostMessage instead of Sendmessage ...?
Yes, if you call asynchronously from a thread you *MAY NOT* call SendMessage cause it is a synchronous call. If you check the docs you'll see that SetWindowText is 'sending' and not 'posting' a message.

PostMessage is thread-safe cause it *adds* a new message to the end of the message queue. But the problem using PostMessage is that the buffer posted needs to keep valid for some time cause the call may be deferred.

So, if you want to update a text of a control from thread you could do:


    static const char* szMsg = "Begin Test";
    pDlg->m_size.PostMessage(WM_SETTEXT, 0, (LPARAM)szMsg);

here the text was not passed as a CString object which may run out of scope while the PostMessage wasn't processed yet but is a literal which additional was made static so that it would keep valid for any compiler (all compilers I know even wouldn't destroy a literal which wasn't statically defined).

>>>> ATLASSERT( nRefs != 0 ); // The debugger stops hier

Why not? Why should the nRefs not be 0 ?

I can't see in the moment how both these problems are related.
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 23592714
>>>> if( _AtlInterlockedDecrement( &nRefs ) <= 0 )

Can you show the code where you call _AtlInterlockedIncrement ?

Did you handle the case where two threads increment nearly same time?

Is the nRefs defined as volatile?
0
 
LVL 45

Expert Comment

by:AndyAinscow
ID: 23597957
>>>That is not so much a difference as long as the thread could not  life longer than the dialog

Not so, some MFC objects are thread specific and will fail (maybe this question is an instance of that behaviour) miserably when one tries to access the functionality directly from another thread.
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 23598108
>>>> some MFC objects are thread specific and will fail
The PostMessage is a thread-safe mechanism to pass messages from a thread to the main thread which runs the message pump. If doing so it is only the lifetime of MFC objects (and their pointers) which could spoil the access.  It is common practice to pass the 'this' pointer of a class instance in the main thread to a dependent  thread. The fact that this doing can fail is not a principal issue but only a matter of carefulness.
0
 
LVL 45

Expert Comment

by:AndyAinscow
ID: 23598148
>>>The PostMessage is a thread-safe mechanism to pass messages from a thread to the main thread which runs the message pump

Yes, but that is not passing an MFC object such as a CWnd pointer and working directly with that object as the questioner attempted to do.  (Which is what your previous comment seemed to imply when you responded to my comment about thread safety)
0
 

Author Comment

by:andy06
ID: 23598759
>>> Can you show the code where you call _AtlInterlockedIncrement ?

Here is how my code looks like:
class CTestDlg : public CDialog
{
// Construction
public:
      CTestDlg(CWnd* pParent = NULL);      // Standard-Konstruktor
      CWinThread* m_thread;
//{{AFX_DATA(CTestDlg)
enum { IDD = IDD_TEST_DIALOG };
      CEdit      m_Size;
      CDisplay      m_Display;
      CImage      m_Image;
      float      m_Erg;
      CString      m_csStatus;
//}}AFX_DATA
//... Code

protected:
Image    Img;
......
DECLARE_EVENTSINK_MAP()
      //}}AFX_MSG
DECLARE_MESSAGE_MAP()
......
public:
int CalculateValue (Image Img);
afx_msg LRESULT OnDisplayImage(WPARAM,LPARAM);
.....
}
BOOL CTestDlg::OnInitDialog()
{
  //...Code
 m_thread=NULL;
//...Code
}
void CTestDlg::OnBnClickedStop()
{
    if (m_thread)
        m_thread->SuspendThread();
}
void CTestDlg::OnBnClickedBStart()
{
     if (m_thread)
    {
       m_thread ->ResumeThread();
   }
    else
    {
        m_thread= AfxBeginThread(ThreadFunction, this,THREAD_PRIORITY_NORMAL,0,0,NULL);
    }
}
UINT  _cdecl ThreadFunction(LPVOID lpParam)
{
CTestDlg *pDlg=(CTestDlg *)lpParam;
CString csMessage,csMessage1;
int H0, Loop;
static const char* szMsg = "Begin Test";
static const char* szMsg 1= "Test done";
pDlg->m_Size.PostMessage(WM_SETTEXT, 0, (lpParam)szMsg);

//Through the function SetNewImage() the image will be
// changed
//CalculateValue perfoms some calculations with the displayed image
//m_Image ist the member variable of the displayed image
//Image display,  H0 calculation and  H0 display
// should be performed  many times

for(Loop=0;Loop<30;Loop++)
{
     //Change the image
      SetNewImage();
    //Display the image
      ::PostMessage(pDlg->GetSafeHwnd(),WM_DISPLAYIMAGE, 0, 0);
       Sleep(1000);
     //Calculate H0
     H0 = pDlg->CalculateValue(pDlg->m_Image.GetImage());
     
      /* Display H0 in the Edit Box*/
      csMessage.Format(_T("%d"), H0);
      ::SetDlgItemText(pDlg->GetSafeHwnd(),IDC_EDIT1,csMessage);
      pDlg->m_editTest.UpdateWindow();

  csMessage1.Format(_T("Loop %d complete"),Loop);
::SetDlgItemText(pDlg->GetSafeHwnd(),IDC_EDIT_SIZE,csMessage1);
pDlg->m_Size.UpdateWindow();
}
pDlg->m_Size.PostMessage(WM_SETTEXT, 0, (lpParam)szMsg1);
AfxEndThread(0);
return 0;
}
Everything is working  fine.Only by debugging occurs the exception...
The other problem I noticed  is that when the Threadfunction is complete ,I can't start the process from the beginning again by clicking on the Start Button. I always have to close the dialog  and compile again...
0
 
LVL 39

Accepted Solution

by:
itsmeandnobodyelse earned 1500 total points
ID: 23599341
>>>> ::SetDlgItemText(pDlg->GetSafeHwnd(),IDC_EDIT1,csMessage);
>>>> ::SetDlgItemText(pDlg->GetSafeHwnd(),IDC_EDIT_SIZE,csMessage1);

Both these statements still will call SendMessage and therefore you do a synchronous call into the message loop from an asynchronously running thread what most likely is the reason for the problems you have.

You better move all these updates into a member function of CTestDialog and send a *private* message to the dialog. Then in the handler of that private message you were back in the main thread and can synchronously do all the updates of the dialog form.

// testdialog.h

#define MY_WM_MESSAGE WM_USER + 1234  // private message ID

struct MessageData
{
     CString msg;
     int         any;
};


// thread.cpp


UINT  _cdecl ThreadFunction(LPVOID lpParam)
{
     CTestDlg *pDlg=(CTestDlg *)lpParam;
     ...
     MessageData* pData  = new MessageData;
     pData->msg = _T("Thread Begin");
     pData->any   = -1;
     pDlg->PostMessage(MY_WM_MESSAGE,  0, (LPARAM)pData);

     ...
}

You can define a handler for that message in your dialog class. As far as I remember the message map macro is

ON_MESSAGE(MY_WM_MESSAGE, yourHandlerFunc)

with that your dialog will called from the message loop and can synchronously update the screen. You can pass all data from thread to dialog via the MessageData struct. After handling the message the MessageData must be deleted in the CTestDialog handler.

>>>> pDlg->GetSafeHwnd()
That isn't necessary. The Dialog won't get a new window handle in its lifetime.
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

Introduction: The undo support, implementing a stack. Continuing from the eigth article about sudoku.   We need a mechanism to keep track of the digits entered so as to implement an undo mechanism.  This should be a ‘Last In First Out’ collec…
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…
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.
Suggested Courses

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