Assertion in VS2008 but not in VS2005 - c++

After switching from VS2005 to VS2008 SP1, I found an issue that I can't explain.
A program works fine under VS2005 in both release and debug mode. Under VS2008, when entering the debugger an assert is raised.
If I let the program run (in debug or release mode), no assertion at all.
I spent almost two days on this and I don't understand what I do wrong.
Description of the program:
I have a MFC dialog based program that creates a user thread (CWinThread) that creates the main dialog of the application.
A worker thread loops infinitely and posts each second a message to the dialog. The message is processed in the gui thread.
Some parts of my code:
The InitInstance of the gui thread:
BOOL CGraphicalThread::InitInstance()
{
CGUIThreadDlg* pDlg = new CGUIThreadDlg();
pDlg->Create(CGUIThreadDlg::IDD);
m_pMainWnd = pDlg;
AfxGetApp()->m_pMainWnd = pDlg;
return TRUE;
}
The worker thread:
UINT ThreadProc(LPVOID pVoid)
{
do
{
AfxGetApp()->m_pMainWnd->PostMessage(WM_APP+1, (WPARAM)new CString("Hello"), NULL);
Sleep(1000);
}
while(!bStopThread);
return 0;
}
The dialog message handler is like this:
LRESULT CGUIThreadDlg::OnMsg(WPARAM wp, LPARAM lp)
{
CListBox* pList = (CListBox*)GetDlgItem(IDC_LIST1);
CString* ps = (CString*)wp;
pList->InsertString(-1, *ps);
delete ps;
return 1L;
}
This works perfectly fine with VS2005.
But with VS2008, but as soon as a put a breakpoint and enter the debugging mode, I have an assertion raised ???
wincore.cpp line 906
CObject* p=NULL;
if(pMap)
{
ASSERT( (p = pMap->LookupPermanent(m_hWnd)) != NULL ||
(p = pMap->LookupTemporary(m_hWnd)) != NULL);
}
ASSERT((CWnd*)p == this); // must be us
// Note: if either of the above asserts fire and you are
// writing a multithreaded application, it is likely that
// you have passed a C++ object from one thread to another
// and have used that object in a way that was not intended.
// (only simple inline wrapper functions should be used)
//
// In general, CWnd objects should be passed by HWND from
// one thread to another. The receiving thread can wrap
// the HWND with a CWnd object by using CWnd::FromHandle.
//
// It is dangerous to pass C++ objects from one thread to
// another, unless the objects are designed to be used in
// such a manner.
If I remove the GUI thread and create the dialog into the CWinApp thread, the problem doesn't occur anymore.
Does anybody have any idea?
Am I doing something wrong?
Thank you

// Note: if either of the above asserts fire and you are
// writing a multithreaded application, it is likely that
// you have passed a C++ object from one thread to another
// and have used that object in a way that was not intended.
// (only simple inline wrapper functions should be used)
//
// In general, CWnd objects should be passed by HWND from
// one thread to another. The receiving thread can wrap
// the HWND with a CWnd object by using CWnd::FromHandle.
//
// It is dangerous to pass C++ objects from one thread to
// another, unless the objects are designed to be used in
// such a manner.

#Ismael: I had already tried that the assert is still fired. The only way I found to remove the assert is to create the dialog into the CWinApp thread.
But this doesn't explain what happens since there's still the worker thread that post to the dialog every second.
Anyway , thanks.
#daanish.rumani: I've checked the wincore.cpp and the CWnd::AssertValid() is exactly the same (but there's of lot of differences in the rest of the files).
I would accept that a piece of code works with VS2005 and not VS2008, but
I can't see what I do wrong.
If I do something wrong, what is the correct way to proceed?
Why the assert is only fired when a breakpoint is hit and I step over the Sleep call?
I can run the program fine, even when its compiled in debug mode, as long as I don't enter the debugger.
Could it be a bug in the debugger?

Related

Updating an CListViewCtrl from worker threads in WTL and C++

As in title I want to add/remove items to a class derived from the WTL CListViewCtrl class from worker threads, but always get "Unhandled exception thrown: read access violation."
I tried Win32 API PostMessage and SendMessage but once the worker thread touches the HWND of CListViewCtrl I get the same exception.
// CListCtrl member function, calling from worker thread
HWND GetHwnd()
{
return hwndListCtrl; // exception here
}
I tried this SafeQueue but once worker thread touches the mutex or queue then exception again.
// SafeQueue is member variable in CListViewCtrl, created in GUI thread
SafeQueue<T> m_SafeQueue;
. . .
// member function in SafeQueue class, calling from worker thread
void enqueue(T t)
{
std::lock_guard<std::mutex> lock(m); // exception here
q->push(t);
}
I tried to create the mutex and queue with new and HeapAlloc/LocalAlloc but same exception again.
I tried Win32 API CreateMutex but no luck, same exception when accessing mutex handle from worker thread.
It works fine when I add items from the GUI thread.
Only way it works from worker threads if I declare HWND or mutex and queue as static/global but I would avoid this since I want to use more than one instance from this listcontrol and I prefer any more elegant way than global variable.
I want to make this class reusable since I want to use it many times with a few modifications (more columns, different colors).
I appreciate any help and idea how I can make this work.
Environment:
VS2015 Community, WTL/C++ and Win10 Pro 64bit
I found the problem that causes access violation exception:
I declared ThreadProc callback function as static member function in CListViewCtrl class.
// DO NOT USE
// in CListViewCtrl
**static** DWORD WINAPI ThreadProc(LPVOID lp)
{
. . .
}
LRESULT OnStartWorkerThread(WORD /*wNotifyCode*/, WORD /*wID*/, HWND . ..)
{
DWORD dw;
::CreateThread(NULL, 0, this->ThreadProc, NULL, 0, &dw);
}
A working solution:
class CListViewCtrl ...
{
// thread-safe queue to store listctrl items to be added later in GUI thread
SafeQueue<CListCtrlItem<nCols> > m_SafeQueue;
// thread ID of the thread in which listctrl was created, saved in OnCreate
DWORD m_dwGuiTid;
// . . .
Check if SafeAddItem function called from GUI or any other threads
BOOL InvokeRequired()
{
if (m_GuiTid == ::GetCurrentThreadId())
return false;
return true;
}
// ...
SafeAddItem member function can be called from GUI and worker threads
void SafeAddItem(CListCtrlItem<nCols> item)
{
if (!InvokeRequired())
{
// we are in GUI thread so just add listctrl item "normal" way
AddItem(item);
return;
}
// we are in other thread so enqueue listctrl item and post a message to GUI
m_SafeQueue.Enqueue(item);
::PostMessage(m_hWnd, WM_ADD_ITEM, 0, 0);
}
// . . .
Message handler of PostMessage, we are in GUI thread
LRESULT OnAddItem(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
{
CListCtrlItem<nCols> item;
while (!m_SafeQueue.Empty())
{
item = m_SafeQueue.Dequeue();
// we are in GUI thread so we can add list ctrl items normal way
AddItem(item);
}
return 1;
}
// ...
}
And now we can add listctrl items from any threads this way. I pass this pointer to ThreadProc in _beginthreadex
m_ListCtrl.SafeAddItem(item);
The question appears to be not really about UI updates from worker thread, but about proper use of worker threads per se.
There is sufficient amount of comments about dangers of doing UI updates: they are all about potential deadlock problem. Most of the updates involve sending a message, which is a blocking API call. While you do the update from worker thread and the calling thread is blocked, any attempt from the handler in the UI to synchronize or otherwise collaboratively work with the worker may result in a deadlock. The only way around this is to prepare update in the worker thread and signal the UI thread (including by posting a message instead of sending it, in terms of SendMessage, PostMessage API) to take over and complete the updates from UI thread.
Back to original problem: you seem to be having a problem with a static thread procedure. The fourth argument in the CreateThread call is:
lpParameter [in, optional]
A pointer to a variable to be passed to the thread.
You have it NULL and you are typically to use it to pass this value to your thread procedure callback. This way you can pass execution back from static function to your class instance:
DWORD CFoo::ThreadProc()
{
// ThreadProc with proper "this" initialization
// HWND h = GetHwnd()...
}
DWORD WINAPI ThreadProc(LPVOID pvParameter)
{
return ((CFoo*) pvParameter)->ThreadProc();
}
LRESULT CFoo::OnStartWorkerThread(WORD /*wNotifyCode*/, WORD /*wID*/, HWND ...)
{
DWORD dw;
::CreateThread(NULL, 0, this->ThreadProc, (LPVOID) this, 0, &dw);
}
Also note that you are not supposed to use CreateThread directly: you have _beginthreadex and AtlCreateThread (related question).
In Windows you should never directly modify a GUI control via a worker thread. In the .NET world if we want to update a control via a worker thread we have to do a platform invoke on a Delegate which basically performs a context switch.
You have a similar problem in WIN32.
There is an excellent article on this subject I will call your attention to. It also discusses various safe workarounds:
https://www.codeproject.com/Articles/552/Using-Worker-Threads
Worker threads and the GUI II: Don't touch the GUI
"That's right. A worker thread must not touch a GUI object. This means that you should not query the state of a control, add something to a list box, set the state of a control, etc.
Why?
Because you can get into a serious deadlock situation. A classic example was posted on one of the discussion boards, and it described something that had happened to me last year. The situation is this: you start a thread, and then decide to wait for the thread to complete. Meanwhile, the thread does something apparently innocuous, such as add something to a list box, or, in the example that was posted, calls FindWindow. In both cases, the process came to a screeching halt, as all threads deadlocked."

Message loop in MFC

I have learned a bit about Win32 API, but now I want to learn MFC. In my ebook, they said that the CWinApp class manages main thread of application, but I can't find something like GetMessage, DispatchMessage functions in this class. So how it can begin the messages loop?
Someone explain this for me please. Sorry, I'm a newer in MFC and my English is bad.
And where can I find some ebooks/tutorials about MFC in Visual Studio?
This all done in the CWinApp:Run section.
After InitInstance returns true, CWinApp:Run is launched and the message-loop takes its role. This message-loop is tricky because it also handles OnIdle calls when the application has nothing to do.
Just look into the source code.
MFC has simplified message handling by using message-maps, programmer mostly need not to bother how message-loop is running, how messages are delivered, and how mapped-messages map to the user defined functions. I would advice you to fiddle around CWnd-derived classes (like frames, dialogs), and see how mapped-messages are calling your functions.
A WM_MOUSEMOVE is calling your OnMouseMove, provided you put an entry ON_WM_MOUSEMOVE - that's an interesting this you should find how it is working. Playing around with CWinApp-derived class isn't good idea.
MFC is somewhat like a wrapped up layer on Win32. The message loop is wrapped up inside a member of CWinThread called Run. And the application class is derived from CWinApp which is in turn derived from CWinThread. This method is not generally overridden. If the message loop code should be read, this method should be overridden and the code can be seen while debugging. It handles the idle message also
int CWinThread::Run()
{
....
for (;;)
{
// phase1: check to see if we can do idle work
while (bIdle &&
!::PeekMessage(&(pState->m_msgCur), NULL, NULL, NULL, PM_NOREMOVE))
{
// call OnIdle while in bIdle state
if (!OnIdle(lIdleCount++))
bIdle = FALSE; // assume "no idle" state
}
// phase2: pump messages while available
do
{
// pump message, but quit on WM_QUIT
if (!PumpMessage())
return ExitInstance();
// reset "no idle" state after pumping "normal" message
//if (IsIdleMessage(&m_msgCur))
if (IsIdleMessage(&(pState->m_msgCur)))
{
bIdle = TRUE;
lIdleCount = 0;
}
} while (::PeekMessage(&(pState->m_msgCur), NULL, NULL, NULL, PM_NOREMOVE));
}
}

Assertion fails after passing HWND to DLL

In our application, we have specialized modules in DLLs, which get control over a window inside our main application window. We pass the window as HWND, not as a CWnd*. Inside the DLL, I use CWnd::FromHandle to get a CWnd*, which I use as a parent to create a CHtmlView inside that window.
As soon as this view is about to be shown, a debug assertion occurs in wincore.cpp:
if(pMap)
{
ASSERT( (p = pMap->LookupPermanent(m_hWnd)) != NULL ||
(p = pMap->LookupTemporary(m_hWnd)) != NULL);
}
ASSERT((CWnd*)p == this); // must be us
// Note: if either of the above asserts fire and you are
// writing a multithreaded application, it is likely that
// you have passed a C++ object from one thread to another
// and have used that object in a way that was not intended.
// (only simple inline wrapper functions should be used)
//
// In general, CWnd objects should be passed by HWND from
// one thread to another. The receiving thread can wrap
// the HWND with a CWnd object by using CWnd::FromHandle.
//
// It is dangerous to pass C++ objects from one thread to
// another, unless the objects are designed to be used in
// such a manner.
Here the line with LookupTemporary fails, altough I used it exactly as described in the comment. In release mode, or if I just place an empty AssertValid-method in my view class, everything works fine.
My question: how can this happen, and is it something I should care about?

Create a dialog in UI Thread causes crash

I tried to create a dialog in a UI thread(CWinThread).
However, it crashes when the CDialog::Create() is called.
I had verified with previous implementation, the dialog is successfully created in non-threading mode.
Does any guru here know the crash reason of creating a dialog in CWinThread?
Without Threading:
class CProduction : public CDialog{
...
}
class CScrollProductionView : public CScrollView{
CProduction *m_pProduction;
...
}
void CScrollProductionView::OnInitialUpdate(){
m_pProduction = new CProduction(0, *m_pVisionAdapter);
m_pProduction->Create(IDD_DLG_PROD, this); //--> created dialog successfully
m_pProduction->ShowWindow(SW_SHOW);
}
Implement UI Thread:
class CProduction : public CDialog{
...
}
class CScrollProductionView : public CScrollView{
CProductionThread* m_pProdThread;
...
}
class CProductionThread : public CWinThread{
CProduction *m_pProduction;
...
}
void CScrollProductionView::OnInitialUpdate(){
m_pProdThread->PostThreadMessage(WM_INITPRODTHREADMESSAGE, PROD_INIT, (LPARAM)m_pVisionAdapter);
m_pProdThread->PostThreadMessage(WM_INITPRODTHREADMESSAGE, PROD_CREATE_DLG, (LPARAM)this);
}
void CProductionThread::InitMessageHandler(WPARAM wParam, LPARAM lParam)
{
printf("Receiving InitMessageHandler msg %d\n", (UINT)wParam);
switch(wParam)
{
case PROD_INIT:
{
CVisionAdapter* pAdapter = (CVisionAdapter*)lParam;
m_pProduction = new CProduction(NULL, *pAdapter);
}
break;
case PROD_CREATE_DLG:
{
CScrollProductionView* pView = (CScrollProductionView*)lParam;
m_pProduction->Create(IDD_DLG_PROD, pView); //--> Crash here
m_pProduction->ShowWindow(SW_SHOW);
}
break;
default:
break;
}
}
Error message:
Debug Assertion Failed! ..
File: .... wincore.cpp
Line: 9906
Thanks you for viewing this question.
Try not to create CWinThread, instead of creating a worker thread, if you have many communication between classes like passing object pointers, strings etc.
You will feel less headache if update the GUI through message handling.
I suspect that the problem is that your CProduction object has not been created when the PROD_CREATE_DLG message is being handled. This may be because of using PostThreadMessage. Using PostThreadMessage is fraught with problems. In particular, the messages may get lost, so the thread never sees the PROD_INIT message.
In the single-threaded code you create your CProduction object right before the Create call. Why don't you do the same in the multi-threaded code?
If you really want to use windows messages to communicate between your threads, I would create a "message only" window (See http://msdn.microsoft.com/en-us/library/ms632599.aspx#message_only) instead, as the window messages will not get lost in the same way that the thread messages do.
Alternatively, use a thread-safe queue to pass custom messages between threads, such as my example queue at http://www.justsoftwaresolutions.co.uk/threading/implementing-a-thread-safe-queue-using-condition-variables.html
The crash is caused by MFC referring invalid window handle (which passed in as parent) during creation.
As a general rule, a thread can access
only MFC objects that it created. This
is because temporary and permanent
Windows handle maps are kept in thread
local storage to help maintain
protection from simultaneous access
from multiple threads.
http://msdn.microsoft.com/en-us/library/h14y172e(VS.71).aspx
an easy fix stated in the MSDN involves changing the code into
...
m_pProdThread->PostThreadMessage(WM_INITPRODTHREADMESSAGE, PROD_CREATE_DLG, (LPARAM)this->GetSafeHwnd());
...
CScrollProductionView* pView = (CScrollProductionView*)CScrollProductionView::FromHandle((HWND)lParam);
m_pProduction->Create(IDD_DLG_PROD, pView);
m_pProduction->ShowWindow(SW_SHOW);
Edit:
Fixed the link to msdn.

I need a message pump that doesn't mess up my open window

My application (the bootstrap application for an installer that I'm working on needs to launch some other applications (my installer and third party installers for my installer's prerequisites) and wait for them to complete. In order to allow the GUI to do screen updates while waiting for an app to complete, I put a message pump in the wait loop using the 'MFC-compatible' example in the Visual Studio documentation on idle loop processing as a guideline. My code (which is in a member function of a CWinApp-derived class) is as follows:
if (::CreateProcess(lpAppName, szCmdLineBuffer, NULL, NULL, TRUE, 0, NULL, NULL,
&StartupInfo, &ProcessInfo))
{
::GetExitCodeProcess(ProcessInfo.hProcess, &dwExitCode);
if (bWait)
while (dwExitCode == STILL_ACTIVE)
{
// In order to allow updates of the GUI to happen while we're waiting for
// the application to finish, we must run a mini message pump here to
// allow messages to go through and get processed. This message pump
// performs much like MFC's main message pump found in CWinThread::Run().
MSG msg;
while (::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
{
if (!PumpMessage())
{
// a termination message (e.g. WM_DESTROY)
// was processed, so we need to stop waiting
dwExitCode = ERROR_CANT_WAIT;
::PostQuitMessage(0);
break;
}
}
// let MFC do its idle processing
LONG nIdle = 0;
while (OnIdle(nIdle++))
;
if (dwExitCode == STILL_ACTIVE) // was a termination message processed?
{
// no; wait for .1 second to see if the application is finished
::WaitForSingleObject(ProcessInfo.hProcess, 100);
::GetExitCodeProcess(ProcessInfo.hProcess, &dwExitCode);
}
}
::CloseHandle(ProcessInfo.hProcess);
::CloseHandle(ProcessInfo.hThread);
}
else
dwExitCode = ::GetLastError();
The problem that I'm having is that, at some point, this message pump seems to free up window and menu handles on the window that I have open at the time this code is run. I did a walk through in the debugger, and at no time did it ever get into the body of the if (!PumpMessage()) statement, so I don't know what's going on here to cause the window and menu handles to go south. If I don't have the message pump, everything works fine, except that the GUI can't update itself while the wait loop is running.
Does anyone have any ideas as to how to make this work? Alternatively, I'd like to launch a worker thread to launch the second app if bWait is TRUE, but I've never done anything with threads before, so I'll need some advice on how to do it without introducing synchronization issues, etc. (Code examples would be greatly appreciated in either case.)
I've also posted this question on the Microsoft forums, and thanks to the help of one Doug Harris at Microsoft, I found out my problem with my HWND and HMENU values was, indeed due to stale CWwnd* and CMenu* pointers (obtained using GetMenu() and GetDialogItem() calls. Getting the pointers again after launching the second app solved that problem. Also, he pointed me to a web site* that showed a better way of doing my loop using MsgWaitForMultipleObjects() to control it that doesn't involve the busy work of waiting a set amount of time and polling the process for an exit code.
My loop now looks like this:
if (bWait)
{
// In order to allow updates of the GUI to happen while we're
// waiting for the application to finish, we must run a message
// pump here to allow messages to go through and get processed.
LONG nIdleCount = 0;
for (;;)
{
MSG msg;
if (::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
PumpMessage();
else //if (!OnIdle(nIdleCount++))
{
nIdleCount = 0;
if (!PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
{
DWORD nRes = ::MsgWaitForMultipleObjects(1, &ProcessInfo.hProcess,
FALSE, INFINITE, QS_ALLEVENTS);
if (nRes == WAIT_OBJECT_0)
break;
}
}
}
}
::GetExitCodeProcess(ProcessInfo.hProcess, &dwExitCode);
*That Web site, if you're curious, is: http://members.cox.net/doug_web/threads.htm
I think your problem is in WaitForSingleObject
Looking in MSDN you see this
Use caution when calling the wait functions and code that directly or indirectly creates windows. If a thread creates any windows, it must process messages. Message broadcasts are sent to all windows in the system. A thread that uses a wait function with no time-out interval may cause the system to become deadlocked. Two examples of code that indirectly creates windows are DDE and the CoInitialize function. Therefore, if you have a thread that creates windows, use MsgWaitForMultipleObjects or MsgWaitForMultipleObjectsEx, rather than WaitForSingleObject.
In my code in the message pump use use MsgWaitForMultipleObjects (doc).
With a call this call.
MsgWaitForMultipleObjects(1, &ProcessInfo.hProcess, FALSE, 100, QS_ALLEVENTS);
This should stop your problem with the resources dissapearing.
When you say that window and menu handles seem to be being freed, do you mean that you've got actual HWND and HMENU values that no longer seem to work, or have you got MFC CWnd* and CMenu* variables that fail?
If the latter, the problem is most likely that you're getting the CWnd* pointers by calling CWnd::FromHandle() (or CMenu::FromHandle()) somewhere (or calling something that calls them), and OnIdle() is discarding them.
The underlying reason is that MFC maintains a map from window (or menu, etc.) handles to CWnd* objects in the system. When CWnd::FromHandle() is called, it looks for a match in the map: if one is found, it's returned. If not, a new, temporary CWnd is created, added to the map, and returned. The idea behind OnIdle() is that when it's called all message processing is done, so OnIdle() discards any of these temporary CWnd objects that still exist. That's why the CWnd::FromHandle() documentation warns that the returned pointer may be temporary.
The "correct" solution to this is to not hang onto the CWnd* pointers returned from CWnd::FromHandle(). Given the simplicity of your application, it might be easier to just remove the call OnIdle(): this shouldn't have any negative effects on an installer.
Of course, this is all something of a guess, but it sounds plausible...
There is a Windows function called DisableProcessWindowsGhosting (see http://msdn.microsoft.com/en-us/library/ms648415(v=vs.85).aspx) that prevents Windows from 'ghosting' your window, and continue updating the window (your animation).