Утверждение в VS2008, но не в VS2005 - PullRequest
1 голос
/ 31 марта 2009

После переключения с VS2005 на VS2008 SP1 я обнаружил проблему, которую не могу объяснить.
Программа отлично работает под VS2005 как в режиме выпуска, так и в режиме отладки. Под VS2008 при входе в отладчик assert повышается.
Если я позволю программе работать (в режиме отладки или выпуска), утверждение вообще не будет.

Я провел почти два дня на этом, и я не понимаю, что я делаю неправильно.

Описание программы: У меня есть программа, основанная на диалоге MFC, которая создает пользовательский поток (CWinThread), который создает главный диалог приложения.
Рабочий поток зацикливается бесконечно и каждую секунду отправляет сообщение в диалог. Сообщение обрабатывается в потоке графического интерфейса.

Некоторые части моего кода:

InitInstance потока графического интерфейса:

BOOL CGraphicalThread::InitInstance()
{
    CGUIThreadDlg* pDlg = new CGUIThreadDlg();
    pDlg->Create(CGUIThreadDlg::IDD);
    m_pMainWnd = pDlg;
    AfxGetApp()->m_pMainWnd = pDlg;
    return TRUE;
}

Рабочий поток:

UINT ThreadProc(LPVOID pVoid)
{
    do
    {
        AfxGetApp()->m_pMainWnd->PostMessage(WM_APP+1, (WPARAM)new CString("Hello"), NULL);
        Sleep(1000);
    }
    while(!bStopThread);

    return 0;
}

Обработчик диалогового сообщения выглядит так:

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

Это прекрасно работает с VS2005. Но с VS2008, но как только поставить точку останова и войти в режим отладки, у меня появилось утверждение ???
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.

Если я удаляю поток GUI и создаю диалог в потоке CWinApp, проблема больше не возникает.

У кого-нибудь есть идеи?
Я что-то не так делаю?

Спасибо

Ответы [ 2 ]

4 голосов
/ 31 марта 2009
// 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.
0 голосов
/ 01 апреля 2009

@ Исмаэль: Я уже пробовал, чтобы обвинение все еще было запущено. Единственный способ удалить assert - создать диалог в потоке CWinApp. Но это не объясняет, что происходит, так как рабочий поток по-прежнему публикуется в диалоге каждую секунду. В любом случае, спасибо.

@daanish.rumani: Я проверил wincore.cpp и CWnd :: AssertValid () точно такой же (но в остальных файлах есть много различий).

Я бы согласился, что часть кода работает с VS2005, а не с VS2008, но

  1. Я не вижу, что я делаю неправильно. Если я делаю что-то не так, как правильно поступить?
  2. Почему утверждение срабатывает только при достижении точки останова, когда я перехожу в режим ожидания? Я могу нормально запустить программу, даже если она скомпилирована в режиме отладки, если я не вхожу в отладчик. Может ли это быть ошибка в отладчике?
...