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
之后为空,则删除操作不会删除原始引用的消息,而是删除引用的新消息。是。如果我不引用,它不会崩溃。但是不是每次都崩溃吗?你能详细解释一下吗?是的,我明白了。非常感谢