VC程序运行一段时间后揭示内存不足
VC程序运行一段时间后提示内存不足
一个MFC写的UDP组播接收数据的程序,程序运行一段时间后就出现内存不足的提示,不知什么原因,望知道的大神指点!
我已经把用的字符指针的地方都换成字符数组了,也就是没有动态申请内存了,还是会出现“内存不足”的提示...
代码如下:
DWORD WINAPI CMainFrame::RecvProc(LPVOID lpParameter)
{
//获取主线程传递的套接字和窗口句柄
SOCKET socket = ((RECVPARAM*) lpParameter)->socket;
HWND hwnd = ((RECVPARAM*) lpParameter)->hwnd;
delete lpParameter;
lpParameter = NULL;
WSANETWORKEVENTS NetWorkEvent;
UINT dwRet;
DataBuffer buffer; //接收缓存
CString strReceived; //接收缓存
CString rxTemp;
CString strTemp;
DWORD DataLen = 0; //预读数据长度
SOCKADDR_IN addrFrom = {0}; //用于保存发送方地址信息
int lenOfAddrFrom = sizeof(SOCKADDR); //初始化数据发送方地址长度
BYTE byteHeader1 = 0; //字符型->字节型,帧头第1字节
BYTE byteHeader2 = 0; //字符型->字节型,帧头第2字节
//创建自动重置的事件对象
WSAEVENT hEvent = WSACreateEvent();
WSAEVENT lphEvents[1];
lphEvents[0] = hEvent;
//重置事件对象状态,将hEvent设置为无信号状态
if(hEvent != NULL)
ResetEvent(hEvent);
while (true)
{
//重置事件对象状态,将hEvent设置为无信号状态
ResetEvent(hEvent);
//注册网络读取事件
dwRet = WSAEventSelect(socket, hEvent, FD_READ);
if(dwRet == SOCKET_ERROR)
return 1;
//请求事件对象
dwRet = WSAWaitForMultipleEvents(1, lphEvents, FALSE, 1, FALSE);
switch(dwRet)
{
case WSA_WAIT_EVENT_0:
{
NetWorkEvent.lNetworkEvents = 0;
dwRet = WSAEnumNetworkEvents(socket, hEvent, &NetWorkEvent);
if(dwRet == SOCKET_ERROR)
return 1;
//收到FD_READ事件通知
if(FD_READ && NetWorkEvent.lNetworkEvents)
{
DataLen = 0; //预读数据长度
if(ioctlsocket(socket, FIONREAD, &DataLen) != 0)
break;
ZeroMemory(recvbuf, 299); //接收缓冲区内存清零
dwRet = recvfrom(socket, recvbuf, DataLen, 0, (SOCKADDR*) &addrFrom, &lenOfAddrFrom);
if(dwRet == SOCKET_ERROR)
{
//int error = WSAGetLastError();
break;
}
ZeroMemory(&buffer, sizeof(buffer)); //缓存清零
buffer.len = DataLen; //有效字节数
memcpy(buffer.buf, recvbuf, DataLen); //缓存数据
byteHeader1 = buffer.buf[50]; //字符型->字节型,帧头第1字节
byteHeader2 = buffer.buf[51]; //字符型->字节型,帧头第2字节
rxTemp.Empty();
strTemp.Empty();
//发现帧头
if (((BYTE) 0xAA == byteHeader1) && ((BYTE) 0xBB == byteHeader2))
{
iRxFrm++; //帧计数加1
if(iRxFrm == 1) //第1帧
{
iRx = 0;
iPacketIndex = 0;
}
//字节计数递增
iRx += buffer.len;
iPacketIndex += buffer.len;
//处理接收到的数据
rxTemp.Empty();
for(unsigned int index = 0; index < buffer.len; index++)
{
BYTE byteTemp = buffer.buf[index]; //字节型
strTemp.Format("%02X", byteTemp); //2位16进制
rxTemp += strTemp;
}
strReceived += rxTemp; //接收3588字节
}
if(iPacketIndex == iPacketLen) //iRxFrm : 11
{
CMainFrame *pMainFrame = (CMainFrame*) AfxGetMainWnd();
CAAAView *CAAAView = (CDispView*) pMainFrame->m_pAAAView;
CAAADoc *pAAADoc = pAAAView->GetDocument();
pAAADoc->str_rx_package = strReceived;
pAAADoc->rx_length = iPacketIndex; //1824
//传递消息
pAAAView->PostMessage(WM_UDP_MSG);
//清空缓存,清零计数(字节)
strReceived.Empty();
iPacketIndex = 0;
}
else if(iPacketIndex > iPacketLen)
{
iRx = 0;
iRxFrm = 0;
iPacketIndex = 0;
strReceived.Empty();
}
else //<11帧的时候继续接收
{
}
//重置事件对象状态,将hEvent设置为无信号状态
ResetEvent(hEvent);
}
}
break;
default:
break;
}
dwRet = WSAEventSelect(socket, hEvent, 0);
}
return 0;
}
------解决思路----------------------
应该是内存泄露,但可能不是这个函数有内存泄露
------解决思路----------------------
PostMessage 可能不是很适合, 可能在View处理消息的时候 又有新消息更新 而导致取数据不正常
------解决思路----------------------
检查是否资源泄漏的办法之一:
在任务管理器 进程 查看 选择列 里面选择:内存使用、虚拟内存大小、句柄数、线程数、USER对象、GDI对象
让你的程序(进程)不退出,循环执行主流程很多遍,越多越好,比如1000000次甚至无限循环,记录以上各数值,再隔至少一小时,越长越好,比如一个月,再记录以上各数值。如果以上两组数值的差较大或随时间流逝不断增加,则铁定有对应资源的资源泄漏!
------解决思路----------------------
资源泄漏可以借助工具
http://blog.****.net/tpriwwq/article/details/19044007
如果需要频繁的new和delete,那就需要自己构造内存池了,
否则时间长了,内存碎片太多,也会导致内存不足
------解决思路----------------------
你要对buffer.len进行判断,不能想当然的认为它会小于某一个值!网络上的事谁也说不准,何况你是个UDP
------解决思路----------------------
如果定位是内存泄露,看下map文件,
------解决思路----------------------
可能是地址越界。。。
一个MFC写的UDP组播接收数据的程序,程序运行一段时间后就出现内存不足的提示,不知什么原因,望知道的大神指点!
我已经把用的字符指针的地方都换成字符数组了,也就是没有动态申请内存了,还是会出现“内存不足”的提示...
代码如下:
DWORD WINAPI CMainFrame::RecvProc(LPVOID lpParameter)
{
//获取主线程传递的套接字和窗口句柄
SOCKET socket = ((RECVPARAM*) lpParameter)->socket;
HWND hwnd = ((RECVPARAM*) lpParameter)->hwnd;
delete lpParameter;
lpParameter = NULL;
WSANETWORKEVENTS NetWorkEvent;
UINT dwRet;
DataBuffer buffer; //接收缓存
CString strReceived; //接收缓存
CString rxTemp;
CString strTemp;
DWORD DataLen = 0; //预读数据长度
SOCKADDR_IN addrFrom = {0}; //用于保存发送方地址信息
int lenOfAddrFrom = sizeof(SOCKADDR); //初始化数据发送方地址长度
BYTE byteHeader1 = 0; //字符型->字节型,帧头第1字节
BYTE byteHeader2 = 0; //字符型->字节型,帧头第2字节
//创建自动重置的事件对象
WSAEVENT hEvent = WSACreateEvent();
WSAEVENT lphEvents[1];
lphEvents[0] = hEvent;
//重置事件对象状态,将hEvent设置为无信号状态
if(hEvent != NULL)
ResetEvent(hEvent);
while (true)
{
//重置事件对象状态,将hEvent设置为无信号状态
ResetEvent(hEvent);
//注册网络读取事件
dwRet = WSAEventSelect(socket, hEvent, FD_READ);
if(dwRet == SOCKET_ERROR)
return 1;
//请求事件对象
dwRet = WSAWaitForMultipleEvents(1, lphEvents, FALSE, 1, FALSE);
switch(dwRet)
{
case WSA_WAIT_EVENT_0:
{
NetWorkEvent.lNetworkEvents = 0;
dwRet = WSAEnumNetworkEvents(socket, hEvent, &NetWorkEvent);
if(dwRet == SOCKET_ERROR)
return 1;
//收到FD_READ事件通知
if(FD_READ && NetWorkEvent.lNetworkEvents)
{
DataLen = 0; //预读数据长度
if(ioctlsocket(socket, FIONREAD, &DataLen) != 0)
break;
ZeroMemory(recvbuf, 299); //接收缓冲区内存清零
dwRet = recvfrom(socket, recvbuf, DataLen, 0, (SOCKADDR*) &addrFrom, &lenOfAddrFrom);
if(dwRet == SOCKET_ERROR)
{
//int error = WSAGetLastError();
break;
}
ZeroMemory(&buffer, sizeof(buffer)); //缓存清零
buffer.len = DataLen; //有效字节数
memcpy(buffer.buf, recvbuf, DataLen); //缓存数据
byteHeader1 = buffer.buf[50]; //字符型->字节型,帧头第1字节
byteHeader2 = buffer.buf[51]; //字符型->字节型,帧头第2字节
rxTemp.Empty();
strTemp.Empty();
//发现帧头
if (((BYTE) 0xAA == byteHeader1) && ((BYTE) 0xBB == byteHeader2))
{
iRxFrm++; //帧计数加1
if(iRxFrm == 1) //第1帧
{
iRx = 0;
iPacketIndex = 0;
}
//字节计数递增
iRx += buffer.len;
iPacketIndex += buffer.len;
//处理接收到的数据
rxTemp.Empty();
for(unsigned int index = 0; index < buffer.len; index++)
{
BYTE byteTemp = buffer.buf[index]; //字节型
strTemp.Format("%02X", byteTemp); //2位16进制
rxTemp += strTemp;
}
strReceived += rxTemp; //接收3588字节
}
if(iPacketIndex == iPacketLen) //iRxFrm : 11
{
CMainFrame *pMainFrame = (CMainFrame*) AfxGetMainWnd();
CAAAView *CAAAView = (CDispView*) pMainFrame->m_pAAAView;
CAAADoc *pAAADoc = pAAAView->GetDocument();
pAAADoc->str_rx_package = strReceived;
pAAADoc->rx_length = iPacketIndex; //1824
//传递消息
pAAAView->PostMessage(WM_UDP_MSG);
//清空缓存,清零计数(字节)
strReceived.Empty();
iPacketIndex = 0;
}
else if(iPacketIndex > iPacketLen)
{
iRx = 0;
iRxFrm = 0;
iPacketIndex = 0;
strReceived.Empty();
}
else //<11帧的时候继续接收
{
}
//重置事件对象状态,将hEvent设置为无信号状态
ResetEvent(hEvent);
}
}
break;
default:
break;
}
dwRet = WSAEventSelect(socket, hEvent, 0);
}
return 0;
}
------解决思路----------------------
应该是内存泄露,但可能不是这个函数有内存泄露
------解决思路----------------------
PostMessage 可能不是很适合, 可能在View处理消息的时候 又有新消息更新 而导致取数据不正常
------解决思路----------------------
检查是否资源泄漏的办法之一:
在任务管理器 进程 查看 选择列 里面选择:内存使用、虚拟内存大小、句柄数、线程数、USER对象、GDI对象
让你的程序(进程)不退出,循环执行主流程很多遍,越多越好,比如1000000次甚至无限循环,记录以上各数值,再隔至少一小时,越长越好,比如一个月,再记录以上各数值。如果以上两组数值的差较大或随时间流逝不断增加,则铁定有对应资源的资源泄漏!
------解决思路----------------------
资源泄漏可以借助工具
http://blog.****.net/tpriwwq/article/details/19044007
如果需要频繁的new和delete,那就需要自己构造内存池了,
否则时间长了,内存碎片太多,也会导致内存不足
------解决思路----------------------
你要对buffer.len进行判断,不能想当然的认为它会小于某一个值!网络上的事谁也说不准,何况你是个UDP
------解决思路----------------------
如果定位是内存泄露,看下map文件,
------解决思路----------------------
可能是地址越界。。。