2017-10-08 4 views
0

delete busMsgでアプリケーションを一定期間実行するとエラーが発生します。エラーの原因を理解できません。これは正しいプロデューサコンシューマモデルではないのですが、stlキューを使用するとエラーの原因は何ですか?

#include "stdafx.h" 
#include "queue.h" 
#include <queue> 
#include <iostream> 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#endif 

CWinApp theApp; 

using namespace std; 

CRITICAL_SECTION m_csReceivedMsgQueue; 
HANDLE m_hReceivedDataEvent; 
HANDLE m_hEventStop; 
queue<CBusMsg* > m_qReceivedMsgQueue; 

class CBusMsg 
{ 
    public: 
    CBusMsg(WORD nAgentID, WORD nAgentExclue, BYTE* pBuf,int nLen) 
    { 
     m_nAgentID=nAgentID; 
     m_nAgentExclue=nAgentExclue; 
     m_nLen=nLen; 
     m_pBuf=new BYTE[m_nLen]; 
     memcpy(m_pBuf,pBuf,nLen); 
    } 
    ~CBusMsg() 
    { 
     if (m_pBuf!=NULL) 
      delete[] m_pBuf; 
    } 
    WORD m_nAgentID; //0:群发,其它:单播 
    WORD m_nAgentExclue; 
    BYTE* m_pBuf; 
    int m_nLen; 
}; 
UINT SendhreadProc(LPVOID pParam) 
{ 
    HANDLE hWaitObjList[2]={m_hEventStop,m_hReceivedDataEvent}; 
    bool haveData = false; 
    DWORD dwWaitRes; 
    for(;;) 
    { 
     if(haveData)//如果还有未处理的数据不等待内核对象直接返回 
     { 
      dwWaitRes=::WaitForMultipleObjects(2,hWaitObjList,FALSE,0); 
     } 
     else//如果没有未处理的数据不等待内核对象直接返回 
     { 
     dwWaitRes=::WaitForMultipleObjects(2,hWaitObjList,FALSE,200); 
     } 
     if((dwWaitRes-WAIT_OBJECT_0)==0)//,索引为0的内核对象被触发,也就是停止线程被触发 
     { 
      break; 
     } 
     haveData = false; 
     try 
     { 
      EnterCriticalSection(&m_csReceivedMsgQueue); 
      if(m_qReceivedMsgQueue.empty()) 
      { 
      LeaveCriticalSection(&m_csReceivedMsgQueue); 
      continue; 
      } 
     CBusMsg*& busMsg = m_qReceivedMsgQueue.front();//取队首元素 
     m_qReceivedMsgQueue.pop();//弹出队首元素 
     if(NULL==busMsg) 
     { 
      LeaveCriticalSection(&m_csReceivedMsgQueue); 
      continue; 
     } 
     //ASSERT(busMsg->m_nLen<=0); 
     //pAgent->SetData(busMsg->m_pBuf,busMsg->m_nLen); 
     haveData = !m_qReceivedMsgQueue.empty(); 
     LeaveCriticalSection(&m_csReceivedMsgQueue); 
     //**************There is the error********************/ 
     delete busMsg; 
     //********************************************************/ 
     //busMsg = NULL; 
     //ProcessData(pAgent); 
    } 
    catch(...) 
    { 
     LeaveCriticalSection(&m_csReceivedMsgQueue); 
    } 
} 
//delete pAgent; 
return 0; 
} 


UINT PushData(LPVOID pParam) 
{ 
BYTE pPacket[1000]; 
memset(pPacket,0,1000); 
for (int i=0;i<100000;i++) 
{ 
    CBusMsg *pBusMsg; 
    pPacket[0]= i; 
    pBusMsg=new CBusMsg(i,0,pPacket,1000); 
    TRACE("请求向队列加消息\n"); 
    EnterCriticalSection(&m_csReceivedMsgQueue); 
    TRACE("开始向队列加消息\n"); 
    m_qReceivedMsgQueue.push(pBusMsg); 
    LeaveCriticalSection(&m_csReceivedMsgQueue); 
    SetEvent(m_hReceivedDataEvent); 

} 
return 0; 
} 

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) 
{ 
    int nRetCode = 0; 
    InitializeCriticalSection(&m_csReceivedMsgQueue); 

    HMODULE hModule = ::GetModuleHandle(NULL); 


    m_hReceivedDataEvent =::CreateEvent(NULL,FALSE,FALSE,NULL); 
    m_hEventStop=::CreateEvent(NULL,FALSE,FALSE,NULL); 

    //创建发送线程 
    CWinThread* m_pSendThread=AfxBeginThread(SendhreadProc,NULL,THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED,NULL); 
    m_pSendThread->m_bAutoDelete=FALSE; 
    m_pSendThread->ResumeThread(); 

    CWinThread* processThread=AfxBeginThread(PushData,NULL,THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED,NULL); 
    processThread->m_bAutoDelete=FALSE; 
    processThread->ResumeThread(); 

    char str[1000]; 
    cin.getline(str,900); 
    return nRetCode; 
} 

答えて

1

問題は、あなたは、キューからポインタへの参照を取る

CBusMsg*& busMsg = m_qReceivedMsgQueue.front();//取队首元素 
m_qReceivedMsgQueue.pop();//弹出队首元素 

ここにあるかもしれません。 次に、参照を無効にするキューをポップします。 プログラムを何度かクラッシュさせるでしょう。 これは、あなたが幸せに

CBusMsg* busMsg = m_qReceivedMsgQueue.front();//取队首元素 
m_qReceivedMsgQueue.pop();//弹出队首元素 

なぜあなただ​​け削除する前に、ロックを解除あなたは

delete busMsg; 

に到達する前に参照されているアドレスが別の何かのために再利用される可能性がありますので、それがクラッシュずになるかもしれないし、キューが空の場合は、同じアドレスを使用して別のものをキューに入れることができます。.pop。次に、元の参照メッセージは削除されず、それが参照されている新しいメッセージが削除されます。

+0

はい、私は参照を取らない、それはクラッシュしません。しかし、それは毎回クラッシュしなかったのですか?もっと詳しく説明できますか? – liu

+0

更新された回答。 – Surt

+0

ええ、私はそれを得る。非常にありがとう! – liu

関連する問題