在程序销毁时释放资源,往往比较容忽略在另外一个线程可能还在使用的资源而先行被销毁,导致程序在退出时崩溃.

比如:
你在主线程中分配了一块内存区域:
//假设其中不存在资源竞争的问题.(否则要用同步控制,嫌麻烦,暂时不做这种处理了).
char* pBuf = new char[10];

然后在另外一个后台线程中:
BOOL bEnd = FA.SE//全局或者静态变量.
DWORD WINPAI CMyClass::OnThreadFunc(LPVOID lpvoid)
{
    CMyClass* pTempMyClass = (CMyclass*)lpvoid;
   
    while(!bEnd)
  {
        WaitForSingleObject(m_hWaitEvent,INFINITE);
    if(bEnd == TRUE)
   {
      break;
    }
       //在这里对这个pBuf进行一些操作.
 pTempMyClass->pBuf……..

  }
  return 1;
}
 
假设你需要从别的地方得到数据,然后在开始运行这个线程,在正常情况下,你执行完你所需要的操作后就这样:
bEnd = TRUE;
SetEvent(m_hWaitEvent);
让这个线程自然的结束.

于是你在程序退出销毁时:
可能这样做:
delete [] pBuf;
pBuf = NULL;
if(m_hThread && m_hWaitEvnet)
{
    bEnd = TRUE;
    SetEvent(m_hWaitEvent);
    WaitForSingleObject(m_hThread,1000);
    CloaseHandle(m_hThread);
    m_hThread  = NULL;
    CloseHandle(m_hWaitEvent);
    m_hWaitEvent = NULL;
}
上面这是在正常情况一种处理,方法.还做了当没有得到数据数据时,当程序退出时,你也能正确的让这个线程自然退出.

但是有一种情况:
 当某种时机下:
你得到数据,于是你开始运行这个线程.
当线程刚刚执行完if(bEnd == TRUE)这句的时候,于是你发出退出程序的命令,于是你做上面的销毁动作。而恰好,你运行完
delete [] pBuf,pBuf = NULL;后,于是线程又恰好要执行你在线程对该pBuf的处理,于是问题出现.必然的要出现无效指针的错误。

怎么避免呢?
很简单销毁资源之前,先停止线程就能避免了.
比如:
if(m_hThread && m_hWaitEvnet)
{
    bEnd = TRUE;
    SetEvent(m_hWaitEvent);
    WaitForSingleObject(m_hThread,1000);
    CloaseHandle(m_hThread);
    m_hThread  = NULL;
    CloseHandle(m_hWaitEvent);
    m_hWaitEvent = NULL;
}

delete [] pBuf;
pBuf = NULL;

因此在多线程种要注意的是:当程序退出,销毁资源的时候,一定要最先退出其中跑起来的线程(线程的退出最好是自然的结束,不要强制的结束).

我在工作就碰见过这种情况:
当时在正常的情况:(一般都能得到数据的情况下,跑另外一个线程).线程一般都结束了。今天恰好跑到一种情况,在数据没有得到情况.我退出了程序.
程序老报错.当时没怎么注意,还以为是别的模块有错误。后来测试的时候,我只加载我一个模块测试,发现退出也有错.
一跟踪发现就是上述类似的问题。恰好在某种情况下就出来,而这种情况也许认为不会出现的,往往就出现了。:(


评论

该日志第一篇评论

发表评论

评论也有版权!