注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

天地不仁,以万物为Googol!

天行有常,不以物喜,不以己悲……

 
 
 

日志

 
 

一个隐讳的错误  

2006-03-03 23:24:23|  分类: 默认分类 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
这是错误么?
 
编译正常,非调试状态下运行正常。但调试状态下退出前抛异常……
 
代码大意如下:
void run()
{
 quitEvent_.create(true, false);//创建退出事件,初始不置位
 fillEvent_.create(true, true);//创建填充事件,初始置位
 
 Event eventArray[2];
 eventArray[0] = quitEvent_;
 eventArray[1] = fillEvent_;
 
 while(Event::waitForMutiply(2, eventArray, Event::waitForever, false, eventID))
 {
  //do sth
 }
 //关闭所有事件
 quitEvent_.close();
 fillEvent_.close();
}
这个函数在调试运行退出时,扔了个异常:Invalid handle。异常位置,是编译器自己生成的一个析构函数。
 
错误原因:
注意到定义: Event eventArray[2];
这里生成了两个新的Event实例,之后通过默认赋值函数,将这两个实例的值,赋为quitEvent_和fillEvent_的值。这里是位赋值,而不是引用,因此当改变quitEvent_或fillEvent_实例的状态时,eventArray是不会跟着变动的。
 
之后,做完循环后,将quitEvent_和fillEvent_手动关闭(实际上,根据我类的实现,这里不用手动关,Event类析构时会自动释放句柄的)。但这时候eventArray还维持原有的状态,也就是指向原来的事件句柄。而这时真正的句柄已经被我close掉了,因此eventArray实际保存了两个invalid handle。
 
再之后,退出函数时,根据c++的实现,要对临时变量正确析构,也就是分别调用eventArray中两个Event实例的析构函数,因为此时这两个实例已经是无效句柄了,结果抛了异常(刚才说了,Event类在析构时会自动释放句柄)。调用eventArray中实例析构函数的地方,是由编译器自动生成的一个数组析构函数,这也是之前提到的那个异常位置。
 
至此,原因已明,改就很好改了。由于Event类的这种情况很特殊,因此我顺手修改了Event类,生明了拷贝构造函数和赋值函数,但没有定义。这样,如果要对Event类做传递,只能通过指针或者引用的方式,也就不会出现上述问题了。
 
至于当初为什么没有添加这个限制,是因为考虑到Event类的实现只有一个Handle成员变量,使用默认位拷贝语义不会造成内存泄漏,也就没有多管。不过,当初考虑不周,只想了内存泄漏,没有想到资源泄漏的问题。
 
对操作系统的理解还是不深啊~~~~~
 
ps 这个东西,真的有那么难理解么?我还想写一篇有关于异步通信时资源不同步的问题的……
  评论这张
 
阅读(144)| 评论(7)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017