andy06
asked on
MFC First chance exception
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::CStringDat a::Release () Line 107 + 0x3 bytes
mfc90d.dll!ATL::CSimpleStr ingT<wchar _t,1>::~CS impleStrin gT<wchar_t ,1>() Line 279
mfc90d.dll!ATL::CStringT<w char_t,Str TraitMFC_D LL<wchar_t ,ATL::ChTr aitsCRT<wc har_t> > >::~CStringT<wchar_t,StrTr aitMFC_DLL <wchar_t,A TL::ChTrai tsCRT<wcha r_t> > >() Line 1011 + 0x8 bytes
Test.exe!CTestDlg::~CTestD lg() + 0x5a bytes
Test.exe!CTestApp::InitIns tance() Line 73 + 0x1c bytes
mfc90d.dll!AfxWinMain(HINS TANCE__ * 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
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::CStringDat
mfc90d.dll!ATL::CSimpleStr
mfc90d.dll!ATL::CStringT<w
Test.exe!CTestDlg::~CTestD
Test.exe!CTestApp::InitIns
mfc90d.dll!AfxWinMain(HINS
Test.exe!WinMain(HINSTANCE
Test.exe!__tmainCRTStartup
Test.exe!WinMainCRTStartup
The first chance exception is at 0x7861d8ec with an access violation at the reading location 0xfffffffc.
What does that mean?
Thank you
Andy
>>>> 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).
>>>> 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).
ASKER
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(csFor mat);
//.....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(csFor mat);
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
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(csFor
//.....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(csFor
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
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).
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).
>> 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(csFor mat), use:
::SendMessage(dlg,MY_CUSTO M_MESSAGE, (WPARAM)&c sFormat,0) ;
//.....Code
...
}
// To the dialog's message map, add:
ON_MESSAGE(MY_CUSTOM_MESSA GE, &CTestDlg::OnMyCustomMessa ge)
// Finally, handle that message like this:
LRESULT CTestDlg::OnMyCustomMessag e(WPARAM wParam, LPARAM)
{
CString* pS = (CString*)wParam;
m_Size.SetWindowText(*pS)
return 0;
}
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(csFor
::SendMessage(dlg,MY_CUSTO
//.....Code
...
}
// To the dialog's message map, add:
ON_MESSAGE(MY_CUSTOM_MESSA
// Finally, handle that message like this:
LRESULT CTestDlg::OnMyCustomMessag
{
CString* pS = (CString*)wParam;
m_Size.SetWindowText(*pS)
return 0;
}
ASKER
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 ?
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 ?
ASKER
I sent my last message before reading the last comment...
Isn't it better to use PostMessage instead of Sendmessage ...?
Isn't it better to use PostMessage instead of Sendmessage ...?
PostMessage is better (SendMessage would force the thread to wait).
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.
>>>> 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::OnNCDestroyWind ow()
{
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::OnBtnClickedSta rtThread()
{
...
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(W M_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.
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::OnNCDestroyWind
{
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
}
}
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::OnBtnClickedSta
{
...
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(W
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.
>>>> 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?
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?
>>>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.
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.
>>>> 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.
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.
>>>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)
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)
ASKER
>>> 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,LPAR AM);
.....
}
BOOL CTestDlg::OnInitDialog()
{
//...Code
m_thread=NULL;
//...Code
}
void CTestDlg::OnBnClickedStop( )
{
if (m_thread)
m_thread->SuspendThread();
}
void CTestDlg::OnBnClickedBStar t()
{
if (m_thread)
{
m_thread ->ResumeThread();
}
else
{
m_thread= AfxBeginThread(ThreadFunct ion, this,THREAD_PRIORITY_NORMA L,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(W M_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->GetSaf eHwnd(),WM _DISPLAYIM AGE, 0, 0);
Sleep(1000);
//Calculate H0
H0 = pDlg->CalculateValue(pDlg- >m_Image.G etImage()) ;
/* Display H0 in the Edit Box*/
csMessage.Format(_T("%d"), H0);
::SetDlgItemText(pDlg->Get SafeHwnd() ,IDC_EDIT1 ,csMessage );
pDlg->m_editTest.UpdateWin dow();
csMessage1.Format(_T("Loop %d complete"),Loop);
::SetDlgItemText(pDlg->Get SafeHwnd() ,IDC_EDIT_ SIZE,csMes sage1);
pDlg->m_Size.UpdateWindow( );
}
pDlg->m_Size.PostMessage(W M_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...
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,LPAR
.....
}
BOOL CTestDlg::OnInitDialog()
{
//...Code
m_thread=NULL;
//...Code
}
void CTestDlg::OnBnClickedStop(
{
if (m_thread)
m_thread->SuspendThread();
}
void CTestDlg::OnBnClickedBStar
{
if (m_thread)
{
m_thread ->ResumeThread();
}
else
{
m_thread= AfxBeginThread(ThreadFunct
}
}
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(W
//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->GetSaf
Sleep(1000);
//Calculate H0
H0 = pDlg->CalculateValue(pDlg-
/* Display H0 in the Edit Box*/
csMessage.Format(_T("%d"),
::SetDlgItemText(pDlg->Get
pDlg->m_editTest.UpdateWin
csMessage1.Format(_T("Loop
::SetDlgItemText(pDlg->Get
pDlg->m_Size.UpdateWindow(
}
pDlg->m_Size.PostMessage(W
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...
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
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