DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
GMXX* gm = (GMXX*)lpParameter; if (WaitForSingleObject(gm->m_readovp.hEvent, MAX_TIMEOUT) == WAIT_OBJECT_0)
{
ResetEvent(gm->m_readovp.hEvent);
if (gm->m_callback)
{
gm->m_callback->ReadCallback(gm->m_data, _tcslen(gm->m_data));
}
}
else
{
CancelIoEx(gm->m_hDevice, NULL);
}

return 0;
}
在上面的代码中,如果gm已经析构了,那么引用它的成员的时候,程序就会crash,请教各位大虾,遇到这样的问题,如何处理?我尝试过RegisterWaitForSingleObject,UnregisterWaitEx,但不清楚UnregisterWaitEx应该在什么时候去调,msdn上说,必须调用UnregisterWaitEx,并且不能在调用RegisterWaitForSingleObject注册的回调中调用。callbackcrash

解决方案 »

  1.   

    整个逻辑都是在你的控制下啊,你知道gm什么时候会析构,在析构后判断一个标志不去调用gm->系列的函数.
      

  2.   

    既然是异步回调,肯定会有问题
    把参数new一份副本转过去,这样异步回调函数中就与gm指针无关了
    m_data = new XXX;
    m_data = gm->m_data;(伪代码,意为拷贝一个副本)
    gm->m_callback->ReadCallback(m_data, _tcslen(m_data));
      

  3.   


    需要用new的方式分配gm->m_data在堆上,然后ReadCallback()里面使用完了以后调一个释放函数来释放gm->m_data
      

  4.   

    传个结构体  把new和delete的函数指针放进去
      

  5.   

    试试boost的shared_ptr & weak_ptr
      

  6.   

    如果你没法控制调用方,什么同步都没用。用try/catch处理异常吧。
      

  7.   

    我是这么做的(VC):
    调用
    CMyClass x
    CMyClass *px = new CMyClass()
    *px = x;
    HANDLE h = (HANDLE)_beginthreadex(NULL, 0, Proc, px, 0, NULL);
    ......回调
    unsigned CALLBACK Proc(void *e)
    {
        CMyclass *p = (CMyClass *)e;
        ......
        delete p;
    }
      

  8.   

    就没看懂你这个问题,是ThreadProc这个线程起来后,gm已经被析构,导致对gm->XX的访问引起crash.还是说你的gm->m_callback->ReadCallback(gm->m_data, _tcslen(gm->m_data),送出去的gm->m_data被上层保存起来,然后在使用时由于gm->m_data被free掉后引起crash.
      

  9.   

    可以用两个事件,其中一个为线程退出事件,在解析传入的参数前,先置退出事件,保证线程在掌控之中
    类似DWORD DemoThread(LPARAM lParam)
    {  
      THREADINFO *pInfo = (THREADINFO *)lParam;
      HANDLE hEvent2[] = 
      {
        pInfo->hExitEvnt, //退出事件。 CreateEvent时用manual-reset方式
        pInfo->hDoEvnt  //做事事件。CreateEvent时用auto-reset方式
      };  BOOL bExitFlag = FALSE;//线程退出标志
      while(!bExitFlag)
      {
        switch(WaitForMultipleObjects(2, hEvent2, FALSE, tmOutTick))
        {
        case(WAIT_OBJECT_0 + 0)://退出事件
          {
            //清理退出 
            bExitFlag = TRUE;
            break;
          }
        case(WAIT_OBJECT_0 + 1)://做事事件
          {
            //……
            break;
          }
        case(WAIT_TIMEOUT)://超时
          {
            //处理超时……
            break;
          }
        default://不期望的事件
          {
            _ASSERT(FALSE);
            bExitFlag = -1;
            break;
          }
        }
      }
      return bExitFlag;
    }