zoukankan      html  css  js  c++  java
  • 【杂谈接口】接口对象的生命周期-对象所占用的内存块清理

    【概述】

    相信经常使用接口的朋友们,经常碰到访问违规异常(Access violation),很多情况下无法理解,认为是编译器的Bug,然后去绕开它,不追其根源,把责任推给IDE,推给编译器(其实本人以前也经常这样想)。其实每个异常都是有原因的,碰到这种问题不要绕开,如果目前无法解决,至少要清楚的知道它出现的起因,不放过每一次追根到底的机会。这才是做程序员的应有的心态。(好像有点扯远了…)

    【问题描述】

    今天公司外包模块中,外包人员反应出现一个很奇怪的问题,说模块中无故出现了AV异常。调试果然如此,而且每次都能出现,每次都能出现的异常就好解决,

    最初的代码如下:

    一个点击按钮事件中包含如下一段代码:

    begin
      ....
      (TmBeanFrameVars.GetBean('ef_pcy_frmTree'as INormalSelector).executeSelect(lvPass);
      ....
    end;

    这样程序在退出函数的时候引发了一个AV异常(end;运行之后),这时候一般对接口不了解的都无从下手。也无从下手进行调试。

    【问题分析】

    首先上面这句简单的访问其实会出现接口的临时变量,而这个变量在函数退出的时候会执行清理,因为executeSelect函数中释放了插件的实例,然后清理临时接口变量时会触发接口对象的__release方法。这个时候引发的一个异常。

    我改造一下代码,让错误在函数退出之前出现,完整代码如下。

    I`VNO]}GF`0}M_PHZR9C2{U

    我用两个局部变量,这样改造后,在执行lvIntf := nil的时候就会出现AV错误。

    image

    我顺便把executeSelect代码贴一下,可以看到这个插件是一个窗体对象实例。在执行这个函数里面会把窗体显示,然后进行了释放,然后退出了函数。

    大概的原因明白后,我们调整下代码,代码如下:

    PFRPD@W3BOX1E[R2B~V[~K9

    注意红色部分,选取完后(释放实例后),然后马上清理接口变量,这个时候,其实内存块应该还是完整的(个人推测),所以清理时不会出现访问违规异常。

    下面我来做个调试证明我的推测

    R7$@CSJ6K@)E74)1XGHER@V

    看红色框出来部分,两个接口变量在释放完后,和之前的指向的内存块中值是一样的(我只获取了一个值,其实可以进行完整对比),然继续执行。

    {8FA%_B][VZU%_SCWT7%V@U

    在看看红色部分,这个时候(其实执行玩cdsOrgan.Append就出现了),lvIntf指向的内存块已经被清理了,因为有新的内存申请。所以后面在清理lvIntf := nil的时候出现访问违规错误。

    好了到了这个时候,我们应该发现引发异常的真正原因了:在清理接口变量时,访问了一块不可预知的内存块,所以导致了访问违规错误。所以请大家在使用接口过程中注意接口的清理工作。

    *认真阅读会收获更多。

    ==========================================

    DIOCP官方社区|MyBean官方社区

    http://www.diocp.org/

    ==========================================

  • 相关阅读:
    vue中webpack和less填坑:项目运行起来报错TypeError: this.getOptions is not a function
    js避坑历险记
    npm -S -D -g i 有什么区别
    Java 中无返回值的方法在使用时应该注意的问题
    java中方法的重载和覆盖
    Java中的内存划分
    git常用操作
    java代码书写易犯错误
    Java基础知识了解
    粘性定位position:sticky
  • 原文地址:https://www.cnblogs.com/DKSoft/p/4138499.html
Copyright © 2011-2022 走看看