【MyBean调试笔记】接口的使用和清理二(关于接口在MyBean中的应用注意)

  • 主题发起人 天地弦
  • 开始时间

天地弦

Unregistered / Unconfirmed
GUEST, unregistred user!
【DEMO信息】
有问题的DEMO, 由【[北京]火鸟】提交
【问题描述】

程序关闭时出现AV错误

zZnkyugQ_9KmfLTcGZg7drsx0C0VOisR.gif
【问题解答】

1:你有一个TDataMoudle的单实例插件,GetBean后他的Owner是vclOwners。在退出程序时清理了VclOwners后,然后清理单实例的接口为nil时出现了AV错误, 因为单实例要保留一份接口, 一般情况是不会出现av的
这里mybean可以优化下,先清理单实例的接口, 但是也不能保证,如果插件在其他DLL时会出现的情况

2:第二个问题是主窗体上面声明了很多插件的实例接口, 如果不提前Free主窗体, 系统关闭主窗体的时候,Delphi会在清理对象的时候会自动清理接口: 接口:= nil, 这样我们都知道 会触发实例的release方法, 但是这个实例已经被释放了,而那块内存可能被破坏。所以主窗体先释放,避免提前清理接口

(插件接口如果是由TComponent类已经他的子类实现, 可以在对象的Destroy时手动清理变量Pointer(AComponentIntf) := nil; 这样不会触发release方法。如果是接口管理生命周期的对象请不要这样做)

这也是我越来越讨厌Delphi自动编译add/release方法的原因了, 虽然component的release方法都基本没什么用, 但是如果这个实例对应的内存地址已经被破坏, 再去访问relase对应的那块地址时可能会参数AV



出现问题的原理就是我刚刚说的哪两种情况
归根到底还是接口赋值为nil的时候,触发了一块无效的对象空间的relase方法





【建议使用规范】

1. 窗体除非特殊的情况, 一般不要注册单实例,在关闭后,最好去释放窗体, 比如Action := caFree。

2. 主窗体提前释放,然后清理插件。推荐写法:

zZnkyugQ_9KmfLTcGZg7drsx0C0VOisR.gif

3. 单实例一般建议用由接口管理对象生命周期插件(继承TInterfacedObject)。而非TCompnent类级子类对象。

查看更多...
 
最后编辑:
顶部