IOCP

截图别人的,自己收藏下:

C/C++ code
   
   
// 监听线程 DWORD WINAPI CService::ClientListen( void * p) { while (TRUE) { SOCKET clientSocket = ::accept(m_pInstance -> m_hServiceSocket,NULL,NULL); if (clientSocket == SOCKET_ERROR) continue ; ::CreateIoCompletionPort((HANDLE)clientSocket,m_pInstance -> m_hServiceIocp, 0 , 0 ); LPIOCONTEXT pIoContext = (LPIOCONTEXT)GlobalAlloc(GPTR, sizeof ( IOCONTEXT)); pIoContext -> wsaBuffer.buf = pIoContext -> pWorkBuffer; pIoContext -> wsaBuffer.len = 10 ; // 下面的代码会引发非常诡异的问题,后面会讲到 UINT nRetVal = ::WSARecv((SOCKET)clientSocket, & (pIoContext -> wsaBuffer), 1 , & (pIoContext -> dwIoSize), & (pIoContext -> dwlFlags), & (pIoContext -> overlapped), NULL); /* 关键位置A */ } return 0 ; }


上面的这段代码看上去没什么问题,但事实上会引发服务崩溃。接着看:
C/C++ code
   
   
// 完成处理线程 DWORD WINAPI CService::DoService( void * p) { DWORD dwBytesXfered = 0 ; DWORD dwKey = 0 ; LPIOCONTEXT pIoContext = NULL; while (TRUE) { GetQueuedCompletionStatus(m_pInstance -> m_ServiceIocp, & dwBytesXfered, & dwKey,(LPOVERLAPPED * )( & pIoContext),INFINITE); GlobalFree(pIoContext); /* 位置B */ } return 0 ; }


上面这段代码看上去也没有问题(其实也确实没问题),但死了我无数的脑细胞。

问题描述:
服务器在接受几个连接之后,要么无故退出,要么就是程序出错Windows要关闭它。
通过调试器运行,提示堆破坏,难道有使用了已释放的内存?检查了3个小时,没找出有可能出现内存错误的地方。
后来实在没办法了,把所有的分配内存的地方地改成GlobalAlloc与GlobalFree,但问题仍旧存在。
最后,干脆把所有的内存释放的地方全去掉,然后逐个调试(加上一个,运行一遍),看看到底是哪个内存出错了,昨晚大部会时间花在这上面了(调试堆破坏我只有这一个办法,不知道高手有其它方法没有?望赐教!)。
最后定位到上面的B处 GlobalFree。

但究竟是什么原因造成的呢?
在网上也找不出所以然,最后几乎快要放弃了,但偶然间改了A处的两个地方,服务器安全运行了(激动啊)!!
改变如下:
UINT nRetVal =::WSARecv((SOCKET)clientSocket,&(pIoContext->wsaBuffer),1, &(pIoContext->dwIoSize),&(pIoContext->dwlFlags),&(pIoContext->overlapped), NULL);
变为
DWORD dwRecvbytes=0;
DWORD dwlFlags=0;
UINT nRetVal =::WSARecv((SOCKET)clientSocket,&(pIoContext->wsaBuffer),1, &dwIoSize,&dwlFlags,&(pIoContext->overlapped), NULL);

也就是说,把WSARecv 第4、第5个参数改成使用局部变量。

现在问题是解决了,但具体原因还只是猜测:
如果不使用局部变量作为参数,那么在IO 等待中系统将会一直引用这两个变量,就算是一个IO完成了,系统内部仍然在使用所以当释放内存后,系统再次使用变量时就破坏了堆数据。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值