destroy, free, freeAndNil, release用法和区别

本文介绍了解决窗体关闭时出现内存访问错误的方法。通过在Close事件中加入Release方法,确保所有事件处理完成后才销毁窗体,有效避免了内存错误。同时对比了destroy、free、freeAndNil及release的使用场景。
 

        最近在集成ZJ的模块的时候,发现当窗体关闭的时候,频繁的弹出内存访问错误,实在是烦躁啊,看了下代码,虽然很惨,但也没发现创建对象需要释放的问题,最后看到窗体关闭的时候,执行了一大段代码,考虑可能是窗体关闭的时候,其中的事件没有执行完成。考虑到这点,在Close事件中加入了Release方法,调试,问题解决。顺便查了下destroy, free, freeAndNil, release用法和区别,如下:

==============================以下方法源自网络========================================

        1)destroy:虚方法
        释放内存,在Tobject中声明为virtual,通常是在其子类中override 它,且要加上inherited关键字,才能保证派生类对象正确地被销毁;但destroy一般不能直接用,为什么?
        假如当一个对象为nil,我们仍然调用destroy,此时会产生错误。因为destroy是虚方法,它要根据对象中的头四个字节找到虚拟方法表Vmt的入口地址,从而找到destroy的入口地址,所以此时对象一定要存在。但free就是静态方法,它只需根据对象引用/指针的类型来确定,即使对象本身不存在也没问题,而且在free中有判断对象是否存在的操作,所以用free比用destroy安全。
        2)free:静态方法
        测试对象是否为nil, 非nil则调用destroy。下面是free的Delphi代码:
        procedure TObject.Free;
        begin
             if Self <> nil then
             Destroy;
        end;
        一静一动,取长补短,岂不妙哉!
        但是调用对象的Destroy只是把对象销毁了,但并没有把对象的引用设为nil,这需要程序员来完成,不过自从Delphi5之后,在sysUtils单元中提供了一个freeAndNil。
        3)freeAndNil;一般方法,非对象方法,非类方法。
        procedure FreeAndNil(var Obj);
        var
            Temp: TObject;
        begin
             Temp := TObject(Obj);
             Pointer(Obj) := nil;
             Temp.Free;
        end;
        建议大家用它代替free/Destroy,以便确保正确地释放对象。
        4)release;TcustomForm中定义的静态方法。
        当窗口中所有的事件处理完之后,才调用free函数。常用在销毁窗口,而在这个窗口中事件处理需要一定的时间的时候,用这个方法能确保窗口事件处理完之后才销毁窗口。下面是TCustomForm.Release的Delphi源代码:
        procedure TCustomForm.Release;
        begin
             PostMessage(Handle, CM_RELEASE, 0, 0);
             //向窗口发CM_RELEASE消息到消息队列,当所有的窗口事件消息处理完之后,
             //再调用CM_RELEASE消息处理过程CMRelease
        end;
        再看看下面CM_RELEASE消息处理过程CMRelease的定义:
        procedure CMRelease(var Message: TMessage); message CM_RELEASE;
        procedure TCustomForm.CMRelease;
        begin
            Free; //最后还是free;
        end;

[dcc32 Error] HIDCommunicator.pas(18): E2003 Undeclared identifier: 'TDeviceHandler' [dcc32 Error] HIDCommunicator.pas(37): E2004 Identifier redeclared: 'TDeviceHandler' [dcc32 Error] HIDCommunicator.pas(57): E2003 Undeclared identifier: 'TObjectList' [dcc32 Error] HIDCommunicator.pas(57): E2029 Expression expected but '.' found [dcc32 Error] HIDCommunicator.pas(57): E2010 Incompatible types: 'TComponent' and 'Boolean' [dcc32 Error] HIDCommunicator.pas(83): E2066 Missing operator or semicolon [dcc32 Error] HIDCommunicator.pas(83): E2034 Too many actual parameters [dcc32 Error] HIDCommunicator.pas(84): E2066 Missing operator or semicolon [dcc32 Error] HIDCommunicator.pas(103): E2029 'TO' expected but identifier 'Count' found [dcc32 Error] HIDCommunicator.pas(105): E2029 'THEN' expected but identifier 'FDevice' found [dcc32 Error] HIDCommunicator.pas(107): E2066 Missing operator or semicolon [dcc32 Error] HIDCommunicator.pas(144): E2250 There is no overloaded version of 'Queue' that can be called with these arguments [dcc32 Error] HIDCommunicator.pas(156): E2037 Declaration of 'TDeviceHandler' differs from previous declaration [dcc32 Error] HIDCommunicator.pas(159): E2075 This form of method call only allowed in methods of derived types [dcc32 Error] HIDCommunicator.pas(160): E2003 Undeclared identifier: 'FCommunicator' [dcc32 Error] HIDCommunicator.pas(160): E2003 Undeclared identifier: 'ACommunicator' [dcc32 Error] HIDCommunicator.pas(161): E2003 Undeclared identifier: 'FDevice' [dcc32 Error] HIDCommunicator.pas(161): E2003 Undeclared identifier: 'ADevice' [dcc32 Error] HIDCommunicator.pas(164): E2066 Missing operator or semicolon [dcc32 Error] HIDCommunicator.pas(164): E2003 Undeclared identifier: 'HandleUnplug' [dcc32 Error] HIDCommunicator.pas(167): E2037 Declaration of 'TDeviceHandler' differs from previous declaration [dcc32 Error] HIDCommunicator.pas(170): E2003 Undeclared identifier: 'FDevice' [dcc32 Error] HIDCommunicator.pas(171): E2066 Missing operator or semicolon [dcc32 Error] HIDCommunicator.pas(173): E2075 This form of method call only allowed in methods of derived types [dcc32 Error] HIDCommunicator.pas(176): E2004 Identifier redeclared: 'TDeviceHandler' [dcc32 Error] HIDCommunicator.pas(179): E2003 Undeclared identifier: 'FDevice' [dcc32 Error] HIDCommunicator.pas(182): E2003 Undeclared identifier: 'FCommunicator' [dcc32 Error] HIDCommunicator.pas(182): E2008 Incompatible types [dcc32 Error] HIDCommunicator.pas(184): E2066 Missing operator or semicolon [dcc32 Error] HIDCommunicator.pas(188): E2003 Undeclared identifier: 'Free' [dcc32 Error] HIDCommunicator.pas(42): E2065 Unsatisfied forward or external declaration: ':2.HandleUnplug' [dcc32 Error] HIDCommunicator.pas(44): E2065 Unsatisfied forward or external declaration: ':2.Create' [dcc32 Error] HIDCommunicator.pas(45): E2065 Unsatisfied forward or external declaration: ':2.Destroy' [dcc32 Hint] HIDCommunicator.pas(24): H2219 Private symbol 'InternalHandleDeviceUnplug' declared but never used [dcc32 Hint] HIDCommunicator.pas(39): H2219 Private symbol 'FCommunicator' declared but never used [dcc32 Hint] HIDCommunicator.pas(40): H2219 Private symbol 'FDevice' declared but never used [dcc32 Hint] HIDCommunicator.pas(42): H2219 Private symbol 'HandleUnplug' declared but never used
09-28
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值