为什么这不是正确的生产者消费者模型以及当我使用 stl 队列时导致错误的原因
why this is not a right Producer consumer model and what causes the error when I use stl queue?
应用程序在行delete busMsg
运行一段时间后会出现错误。我不明白错误是如何产生的。
#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;
}
问题可能在这里
CBusMsg*& busMsg = m_qReceivedMsgQueue.front();//取队首元素
m_qReceivedMsgQueue.pop();//弹出队首元素
从队列中获取对指针的引用。然后,您弹出队列,使引用无效。这将使程序崩溃几次。这可能会让你更快乐
CBusMsg* busMsg = m_qReceivedMsgQueue.front();//取队首元素
m_qReceivedMsgQueue.pop();//弹出队首元素
为什么它会崩溃,因为引用的地址可能会在您到达之前被重用于其他内容
delete busMsg;
您在删除之前释放锁,在这段时间内,另一个人可以使用相同的地址将新的东西放入队列中,例如,如果队列在.pop
后为空。然后,删除操作不会删除原始引用的消息,而是删除它引用的新消息。
相关文章:
- 使用2个键的cpp-stl::优先级队列排序不正确
- 如何将 STL 队列推送函数绑定到 std::函数?
- 为什么某些 STL 容器(堆栈、队列、优先级队列)不支持迭代器?
- 如何将元素从 STL 队列传递到函数?
- 为什么STL优先级队列错误地分配了我的类对象
- 如何检查队列是否使用 STL 排序
- C++ 14 个 stl 容器队列
- 从 STL 优先级队列C++ (QtCreator) 打印结构
- 在 stl 中迭代结构类型的队列
- 使用队列和列表 STL 进行C++分配。在将数据填充到列表或队列中然后打印该数据时遇到问题
- 迭代C STL队列
- 如何删除在没有STL的队列中存储在数组中的第一个字符串元素
- 在STL队列容器中订购
- 为什么这不是正确的生产者消费者模型以及当我使用 stl 队列时导致错误的原因
- 简单,但找不到:使用类型类的 STL 队列的成员变量的语法
- 从 STL 优先级队列创建最小堆
- stl 优先级队列中的堆管理是否调用复制构造函数
- C STL优先级队列获得BAD_ALLOC
- 如何在类构造函数中设置 STL 队列的大小
- 我如何覆盖队列STL对象中的一些函数