读书人

局部变量性命期在 作为异步函数的参数

发布时间: 2012-10-07 17:28:51 作者: rapoo

局部变量生命期在 作为异步函数的参数的使用
看个代码片段:


case OP_READ://完成一个接受请求
{
pPerIO->buf[dwTrans]='\0';

WSABUF buf;

buf.buf=pPerIO->buf;

buf.len=BUFFER_SIZE;

pPerIO->nOperationType=OP_READ;

DWORD nFlags=0;

WSARecv(pPerHandle->s,&buf,1,&dwTrans,&nFlags,&pPerIO->ol,NULL); //look here
}
break;

看到没有,在 case中有个花括号,而WSARecv函数中传入的参数大多是局部变量,是传指针的方式。

WSARecv这个函数有个特点: 立即返回(非堵塞函数),返回之后,变量生命期已经接受,而WSARecv 依然在执行!!!


不觉得会不会出什么问题呢?



问题2: 重叠io+完成端口 与 “ 重叠io+ 工作线程” 的方式谁好,付理由?

问题3: 重叠io和完成端口 为什么后者比前者好, 都是通过WSARecv, WSASend发送命令给内核啊,


三个问题, 谢谢大家

[解决办法]
本人能力有限,只能回答第一个问题:
WSARecv虽然是异步调用,他只是把内核的缓冲区复制到你给他的内存中(如果有数据, 如果没有数据就立即返回,而不会阻塞)
[解决办法]
程序每次进入你的代码段,就为你的局部变量分配地址,然后调用一次WSARecv。因此单纯从程序运行来看,使用局部变量是没有问题的,只是你这段代码唯一的实际意义就是将从缓存区读走,然后不作任何处理,实际上就是丢弃信息。因此,这段代码看起来是没有什么太多实际意义的。


“变量生命期已经结束,而WSARecv 依然在执行!”这是你自己的误解。
WSARecv(pPerHandle->s,&buf,1,&dwTrans,&nFlags,&pPerIO->ol,NULL);
如果是异步IO,则WSARecv发现没有数据,就会直接返回,意味着函数也会随着结束;如果是同步,则函数会挂起等待数据的到来,这时的变量的生命周期也就没有结束。总之,这种变量生命周期和函数执行之间的关系,编译器已经帮你处理好了,只要代码符合语法规则,就不用操心了。

问题2: 重叠io+完成端口 与 “ 重叠io+ 工作线程” 的方式谁好,付理由?
问题3: 重叠io和完成端口 为什么后者比前者好, 都是通过WSARecv, WSASend发送命令给内核啊
----------------------------
不太明白这个问题。端口和线程是完全没有可比性的。可能你要表达程序设计结构方面的问题?
也许你看的书或者什么文章,本身就存在概念模糊甚至错误的地方。

[解决办法]

探讨

程序每次进入你的代码段,就为你的局部变量分配地址,然后调用一次WSARecv。因此单纯从程序运行来看,使用局部变量是没有问题的,只是你这段代码唯一的实际意义就是将从缓存区读走,然后不作任何处理,实际上就是丢弃信息。因此,这段代码看起来是没有什么太多实际意义的。


“变量生命期已经结束,而WSARecv 依然在执行!”这是你自己的误解。
WSARecv(pPerHandle->s,&am……

[解决办法]
1.你这个用法显然是错误的,既然已经知道离开作用域时局部变量被销毁,你还能期待异步线程在使用此野指针时能正常工作?正确的做法是凡是传给异步线程的内存必须一直保存到其任务完成,一般在堆上分配内存并保存到相关全局对象上以便后续处理就行了

2.完成端口和异步线程的区别:简单地说就是完成端口内部自己管理了异步线程,省去了你自己去写的麻烦也比大多数人写得要好。

3.完成端口和重叠IO的区别:重叠IO只是异步逻辑的一种叫法,而完成端口是实现异步逻辑的众多机制中的其中一种,select也是一种异步逻辑,只不过因为它要把数据在应用]和内核间来回拷贝导致大数据量时效率不高,所以在unix系统上进化成了kqueue/epoll,在windows上就进化成了完成端口。
[解决办法]
呵呵,答案正确与否,不能光看裤衩数量, 4个裤衩能说明啥问题啊?

顶 7楼,基本同意8楼关于问题1的说法。

读书人网 >C++

热点推荐