C++ 为什么这不是一个正确的生产者-消费者模型?当我使用stl队列时,是什么导致了错误?

C++ 为什么这不是一个正确的生产者-消费者模型?当我使用stl队列时,是什么导致了错误?,c++,multithreading,C++,Multithreading,应用程序运行一段时间后,在delete busmg行将出现错误。我不明白错误是如何产生的 #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_csReceivedMsgQ

应用程序运行一段时间后,在
delete busmg
行将出现错误。我不明白错误是如何产生的

#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;
}
#包括“stdafx.h”
#包括“queue.h”
#包括
#包括
#ifdef_调试
#定义新调试\u新
#恩迪夫
CWinApp-theApp;
使用名称空间std;
临界段m_csReceivedMsgQueue;
处理m_hReceivedDataEvent;
处理m_hEventStop;
队列m_qReceivedMsgQueue;
类CBusMsg
{
公众:
CBusMsg(单词nAgentID,单词nAgentExclue,字节*pBuf,int-nLen)
{
m_nAgentID=nAgentID;
m_nAgentExclue=nAgentExclue;
m_nLen=nLen;
m_pBuf=新字节[m_nLen];
memcpy(m_pBuf,pBuf,nLen);
}
~CBusMsg()
{
如果(m_pBuf!=NULL)
删除[]m_pBuf;
}
单词m_nAgentID;//0:群发,其它:单播
单词m_nAgentExclue;
字节*m_pBuf;
国际货币基金组织;
};
UINT sendreadproc(LPVOID pParam)
{   
HANDLE-hWaitObjList[2]={m_-hEventStop,m_-hReceivedDataEvent};
bool-haveData=false;
德沃德·德韦特尔;
对于(;;)
{
if(haveData)//如果还有未处理的数据不等待内核对象直接返回
{
dwWaitRes=::WaitForMultipleObjects(2,hWaitObjList,FALSE,0);
}
否则//如果没有未处理的数据不等待内核对象直接返回
{
dwWaitRes=::WaitForMultipleObjects(2,hWaitObjList,FALSE,200);
}
如果((dwWaitRes-WAIT_OBJECT_0)=0)/,索引为0的内核对象被触发,也就是停止线程被触发
{
打破
}
haveData=false;
尝试
{
输入关键部分(&m_csReceivedMsgQueue);
if(m_qReceivedMsgQueue.empty())
{
离开关键部分(&m_csReceivedMsgQueue);
持续
}
CBusMsg*&busmg=m_qReceivedMsgQueue.front()//取队首元素
mqreceivedmsgqueue.pop()//弹出队首元素
如果(NULL==BUSMG)
{
离开关键部分(&m_csReceivedMsgQueue);
持续
}
//断言(busmg->m_nLenSetData(busmg->m_pBuf,busmg->m_nLen);
haveData=!m_qReceivedMsgQueue.empty();
离开关键部分(&m_csReceivedMsgQueue);
//**************这是一个错误********************/
删除busmg;
//********************************************************/
//busMsg=NULL;
//过程数据(页面);
}
捕获(…)
{
离开关键部分(&m_csReceivedMsgQueue);
}
}
//删除寻呼机;
返回0;
}
UINT PushData(LPVOID pParam)
{
字节pPacket[1000];
memset(pPacket,01000);
对于(int i=0;im_bAutoDelete=FALSE;
m_pSendThread->ResumeThread();
CWinThread*processThread=AfxBeginThread(PushData,NULL,THREAD\u PRIORITY\u NORMAL,0,CREATE\u SUSPENDED,NULL);
processThread->m_bAutoDelete=FALSE;
processThread->ResumeThread();
char-str[1000];
cin.getline(str,900);
返回nRetCode;
}

问题可能就在这里

CBusMsg*& busMsg = m_qReceivedMsgQueue.front();//取队首元素
m_qReceivedMsgQueue.pop();//弹出队首元素
从队列中获取指针的引用。 然后弹出队列,使引用无效。 这将使程序有时崩溃。 这可能会让你更快乐

CBusMsg* busMsg = m_qReceivedMsgQueue.front();//取队首元素
m_qReceivedMsgQueue.pop();//弹出队首元素
为什么它会崩溃,因为在您访问之前,引用的地址可能会被重新用于其他用途

delete busMsg;

您在删除之前释放锁,在此期间,另一个用户可以使用相同的地址在队列中放入新的内容,例如,如果队列在
.pop
之后为空,则删除操作不会删除原始引用的消息,而是删除引用的新消息。

是。如果我不引用,它不会崩溃。但是不是每次都崩溃吗?你能详细解释一下吗?是的,我明白了。非常感谢