抓虫记之十:误杀自己的命令

 

今天一位同事找我看了一个非常有意思的BUG,在一个弹出的非模态窗体上面,按下【Ctrl + S】,弹出保存文件窗体,点击取消好,报出0x80808080地址访问错误。但是程序中没有停下断点。

先看这个地址很有意思吧?这么有规律的,绝对很有来头,不过这个BUG先不讲这个。

这个BUG还是很容易跟踪下来的。不过说是容易,也费了不少劲,因为消息循环有其特有的特征,在WndProc里是不能随便下断点的。那如何跟踪呢?

有人想到ExceptionLog,加入异常机制。这反而麻烦了。其实就是慢慢跟踪代码,进行简单分析。基本就能定位到了。

原来,在弹出的窗体中的消息处理中,响应完消息后,会调用自己定义的消息回调事件,如下:

inherited WnProc(Msg);

If Assigned(FOnMessage) then FOnMessage(Self, Msg);

第一行代码,在基类中,会自动调用全局消息处理,关键是,这位同事的系统中,在保存的时候,释放掉了一些窗体,包括当前弹出的窗体。

也就是说,第一行代码执行完成之后,当前对象实例就已经被释放了。所以第二句话,就会出现地址访问错误了。

那么,如何解决这个问题呢?这个问题与一般的不太一样,因为他涉及到了消息循环。因此我的建议是,将保存事务做完之后,再调用释放窗体的操作,且该操作作为一个消息处理,排到消息队列中。即先声明一个自定义消息函数:

procedure DoSomeEvent(var Message); message GM_SelfMessage;

并且在保存完成之后通过PostMessage的方式,调用该函数。这样就能保证WndProc函数处理完成之后,才会调用到窗体释放的函数。这个错误就应该能够避免了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值