IOCP应用中,有关内存释放的几个需要注意的地方

写文章最主要目的是备忘,以免一些好不容易想通的问题,被人体新陈代谢给清理出大脑,最后忘得一干二净,要是平常没个记录的好习惯会很心累。


只不过再充分的准备,再自信满满,再运筹帷幄,也敌不过世事无常。


昨天,我严格按照卸载的标准流程删除软件,没想到竟然把我D:\tools文件夹给整个端掉了,以前的记录文档,全没了。


更苦的是,我并没有立即发现,而是又往D盘装了若干东西之后才知道TOOLS文件夹没了,数据恢复半天连一点边角料都没抢救回来。


这件事给我的教训是:资料还得在网上也备一份


好了,现在就开始备一份吧。


大多数时候,IOCP有关的内存释放,都要等GetQueuedCompletionStatus函数取回一个完成包(甭管这包是好的坏的还是出错的),不过有些情况特殊,比如:


1.调用CreateIoCompletionPort绑定套接字的时候

2.调用WSASend函数投递发送数据请求的时候

3.调用WSARecv函数投递接收数据请求的时候

4.调用AccetptEx函数投递接收连接请求的时候

5.调用ConnectEx......


调用这几个函数一旦出错,就应该立即释放一些之前为这些调用准备好的内存。其实想来也简单,IOCP这种托儿所都没成功把你家孩子收去管制,那出了问题肯定不应该去找IOCP,根本不归它管,它负什么责呢?


当然,这里所谓的出错,不能包括WSA_IO_PENDING,这个错误表明IOCP已经接收委托,只不过事情能不能办好得等待以后的进一步通知。


所以,关键还是看IOCP有没有接手你的请托,如果接手了,那么内存释放问题需要等Get函数返回,如果请托都没有成功,那么就应该在请托失败之后立即释放一些动态分配的内存。


=========================================================================================================

差不多了,下面记录一下WSASend的返回值问题

=========================================================================================================

先看MSDN怎么说

If no error occurs and the send operation has completed immediately, WSASend returns zero.(无错,且投递操作立刻完成,返回0)

网上还有一种说法,是这样的: “如果投递操作立刻完成,WSASend返回投递成功的字节数”.


这种说法也不知道被复制粘贴了多少次,经常能看到,明显跟官方说法对不上,但也不能说完全错了,网上搜了搜,猜测它最初来源应该在这里:


http://www.cppblog.com/sleepwom/archive/2009/01/31/72726.html


这位老兄很有意思,你翻译就对照句式,工整的翻译嘛,非要把自己的理解一并放上,这样很容易引起误解,有人可能真以为WSASend会返回一个大于0的整数,进而考虑数据重发的问题。


其实他这么说是根据MSDN后面的一段解释:

If an overlapped operation completes immediately, WSASend returns a value of zero and the lpNumberOfBytesSent parameter is updated with the number of bytes sent. If the overlapped operation is successfully initiated and will complete later, WSASend returns SOCKET_ERROR and indicates error code WSA_IO_PENDING. In this case, lpNumberOfBytesSent is not updated. 

如果重叠操作立即完成,WSASend返回0的同时,它的第4个参数lpNumberOfBytesSent所指向的内存空间,会被系统写入本次操作实际拷贝进系统缓冲区的字节数。

如果成功发起了一次重叠操作,且稍后才能完成,则WSASend返回SOCKET_ERROR并指定一个叫做WSA_IO_PENDING的错误码,这种情况下,lpNumberOfBytesSent所指向的内存空间是不会被写入数值的。


那位老兄的理解肯定是没错的,只是在翻译的时候想法太多,把函数的返回值和参数的返回值两者融合了。


说到这里,引出了一个网上讨论很多的问题,WSASend所投递的数据能否一次性全部复制进系统缓冲区,也即WSASend能否一次性发送完全的问题。


其实按我的理解,可以放心大胆的投递多个重叠的WSASend,同时检查WSASend的第四个参数,如果发送不完全就补发,至于Get函数所返回的完成包,则不需要去多疑惑,肯定不会出现发送不完全的情况,否则重叠的意义何在?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值