This may be due to a corruption of the heap...

yuyunliuhen 2010-06-06 08:11:39
错误提示:http://blog.csdn.net/yuyunliuhen/archive/2010/06/06/5650391.aspx
在客户端使用事件网络模型的时候,接收的数据直接加入环形缓冲区,使用的时候每次NEW新的内存的时候就出现以上的错误,
代码如下:

unsigned int CSClient::WorkThreadFunction(void *pV)
{
int nError = 0;
CSClient* pThis = (CSClient*)pV;
while(1)
{
DWORD dwEvent = 0;
// Wait for one of the sockets to receive I/O notification and
if ((dwEvent = WSAWaitForMultipleEvents(1,&pThis->m_Event, FALSE,WSA_INFINITE, FALSE)) == WSA_WAIT_FAILED)
{
printf("WSAWaitForMultipleEvents failed with error %d\n", WSAGetLastError());
closesocket(pThis->m_Sock);
pThis->m_Sock = INVALID_SOCKET;
_endthreadex(0);
return 0;
}
if(WSA_WAIT_TIMEOUT == dwEvent)
{

}
else
{
WSANETWORKEVENTS NetworkEvents;
dwEvent = dwEvent - WAIT_OBJECT_0;
if (WSAEnumNetworkEvents(pThis->m_Sock, pThis->m_Event, &NetworkEvents) == SOCKET_ERROR)
{
printf("WSAEnumNetworkEvents failed with error %d\n", WSAGetLastError());
return 0;
}
if (NetworkEvents.lNetworkEvents & FD_READ)
{
if (NetworkEvents.iErrorCode[FD_READ_BIT] != 0)
{
printf("FD_READ failed with error %d\n", NetworkEvents.iErrorCode[FD_READ_BIT]);
break;
}
DWORD dwFlags = 0;
DWORD dwRecvBytes = 0;
WSABUF WSABuf;
WSABuf.len = DATA_BUFSIZE;

WSABuf.buf = (char*)(pThis->m_RingBuf.GetBuffer() + pThis->m_RingBuf.GetwritePos());
//dwFlags is nessary
if(WSARecv(pThis->m_Sock,&WSABuf,1,&dwRecvBytes,&dwFlags,NULL,NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != WSAEWOULDBLOCK)
{
printf("WSASend() failed with error %d\n", WSAGetLastError());
}
}
pThis->m_LockBuffer.Enter();
pThis->m_RingBuf.Write((BYTE*)WSABuf.buf,dwRecvBytes);
pThis->GetMsg();
pThis->m_LockBuffer.Leave();


}
else if(NetworkEvents.lNetworkEvents & FD_CLOSE)
{
if (NetworkEvents.iErrorCode[FD_CLOSE_BIT] != 0)
{
printf("FD_CLOSE failed with error %d\n", NetworkEvents.iErrorCode[FD_CLOSE_BIT]);
break;
}
closesocket(pThis->m_Sock);
WSACleanup();
}
}
}
return 0;
}


开始猜想可能是直接将数据写入缓冲区中,当缓冲区大小不够的时候,重新分配,原有的内存已释放,WSABuf.buf = (char*)(pThis->m_RingBuf.GetBuffer() + pThis->m_RingBuf.GetwritePos()); 再次使用原有的已释放的地址会出问题,
于是就换成这样:

unsigned int CSClient::WorkThreadFunction(void *pV)
{
int nError = 0;
CSClient* pThis = (CSClient*)pV;
while(1)
{
DWORD dwEvent = 0;
// Wait for one of the sockets to receive I/O notification and
if ((dwEvent = WSAWaitForMultipleEvents(1,&pThis->m_Event, FALSE,WSA_INFINITE, FALSE)) == WSA_WAIT_FAILED)
{
printf("WSAWaitForMultipleEvents failed with error %d\n", WSAGetLastError());
closesocket(pThis->m_Sock);
pThis->m_Sock = INVALID_SOCKET;
_endthreadex(0);
return 0;
}
if(WSA_WAIT_TIMEOUT == dwEvent)
{

}
else
{
WSANETWORKEVENTS NetworkEvents;
dwEvent = dwEvent - WAIT_OBJECT_0;
if (WSAEnumNetworkEvents(pThis->m_Sock, pThis->m_Event, &NetworkEvents) == SOCKET_ERROR)
{
printf("WSAEnumNetworkEvents failed with error %d\n", WSAGetLastError());
return 0;
}
if (NetworkEvents.lNetworkEvents & FD_READ)
{
if (NetworkEvents.iErrorCode[FD_READ_BIT] != 0)
{
printf("FD_READ failed with error %d\n", NetworkEvents.iErrorCode[FD_READ_BIT]);
break;
}
DWORD dwFlags = 0;
DWORD dwRecvBytes = 0;
WSABUF WSABuf;
WSABuf.len = DATA_BUFSIZE;
PBUFFER pBuffer = new BUFFER();
if(pBuffer)
{
WSABuf.buf = (char*)(pBuffer + 1);
if(WSARecv(pThis->m_Sock,&WSABuf,1,&dwRecvBytes,&dwFlags,NULL,NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != WSAEWOULDBLOCK)
{
printf("WSASend() failed with error %d\n", WSAGetLastError());
}
}
}

}
else if(NetworkEvents.lNetworkEvents & FD_CLOSE)
{
if (NetworkEvents.iErrorCode[FD_CLOSE_BIT] != 0)
{
printf("FD_CLOSE failed with error %d\n", NetworkEvents.iErrorCode[FD_CLOSE_BIT]);
break;
}
closesocket(pThis->m_Sock);
WSACleanup();
}
}
}
return 0;
}


貌似问题还在。如果大家之前遇到类似的问题,麻烦指点下,谢谢先。
环形缓冲区的代码:http://blog.csdn.net/yuyunliuhen/archive/2010/05/16/5598783.aspx
...全文
1011 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
jixingzhong 2010-06-06
  • 打赏
  • 举报
回复
作为缓冲,还是使用基本的数据类型吧...
arong1234 2010-06-06
  • 打赏
  • 举报
回复
GetBuffer是CString的那个?一旦GetBuffer,任何对CString对象的后续操作都可能是危险的,你必须ReleaseBuffer后才能继续使用它!

不要使用CString,std::string来做这种缓冲,直接用char*
CrySleeper 2010-06-06
  • 打赏
  • 举报
回复
这句
WSABuf.buf = (char*)(pThis->m_RingBuf.GetBuffer() + pThis->m_RingBuf.GetwritePos());
改为
WSABuf.buf = new char[DATA_BUFSIZE];

...
记得delete[] WSABuf.buf
AlanBruce 2010-06-06
  • 打赏
  • 举报
回复
UP

UP
yuyunliuhen 2010-06-06
  • 打赏
  • 举报
回复
问题已经找出,内存写溢出了,本想通过环形缓冲直接接收系统的数据,但是系统数据的大小大于缓冲区的剩余大小,所以还是不能省,还得加上内存池来接收,谢谢各位。

64,683

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧