• 一个小问题引发的论证思考


        今天,有一个朋友,问了俺一个莫名其妙的问题,问的俺是一愣一愣的,搞了半天愣是没搞明白。他提问的原话是:

    一文件流没有创建,怎么判断呢

    这个问题还真把我问倒了,我压根就没明白这是个啥意思,后来他说了半天之后,我还是没明白是啥,最后他索性给了一个让我郁闷了半天的代码。如下:

    var
    Stream : TMemoryStream;
    aSkinName : Pchar;
    vStrings : TStrings;
    begin
    inherited;
    vHandle :
    = LoadLibrary(Pchar(Gv_SkinFile)); //动态载入DLL,并返回其句柄
    //Stream := TMemoryStream.Create;
    try
    if vHandle <> 0 then //
    begin
    @GetSkin:
    =GetProcAddress(vHandle, 'GetSkin');
    end;
    if not (@GetSkin = nil) then
    begin
    Stream :
    = TMemoryStream.Create;
    aSkinName :
    = pchar(Gv_SkinName);
    GetSkin(aSkinName,Stream);
    with Unit_CommonDm.CommonDm.SkinData do
    begin
    LoadFromStream(stream);
    if not Active then Active := true;
    end;
    end else
    begin
    //RaiseLastWin32Error;
    end;
    finally

    FreeLibrary(vHandle);
    //调用完毕收回DLL占用的资源
    stream :
    = nil ;
    if stream = nil then
    stream.free;

    end;
    然后反复强调了最后finally中的一段代码

    stream := nil ;
    if stream = nil then
    stream.free;
    看到这个代码,我还真是郁闷了!后来才明白,原来他是想知道Stream到底有没有被创建过,如果没创建,那么就是个坏指针,是不用释放的。结果给整出来了这么个东西!
    起初,我直接说,这个代码肯定报错,但是他反复强调,绝对不错,并且让我试试。于是,我试验了一下,哈,果然不报错啊!我在Delphi中测试的代码如下
    var
    stream: TMemoryStream;
    begin
    stream :
    = TMemoryStream.Create;
    stream.Size :
    = 234;
    stream :
    = nil;
    if stream = nil then
    stream.Free;
    end;

    这样写,居然不会出错哦!那么这个创建的TMemoryStream到底释放了没有呢?想都不用想,那是肯定没释放的,也就是说有内存泄露,不信的可以用FastMM查看看。至于为

    啥出错,我们需要去看TObject的Destroy的代码,这个在Delphi中式没有实现的,我们在调试过程中打开Delphi的CPU调试窗口查看一下汇编代码

    TObject.Free:
    00403A00 85C0             test eax,eax //这里检查了释放的指针是否为nil
    00403A02 7407             jz $00403a0b//如果为nil向后跳7字节,也就是直接跳到ret
    00403A04 B201             mov dl,$01
    00403A06 8B08             mov ecx,[eax]
    00403A08 FF51FC           call dword ptr [ecx-$04]
    00403A0B C3               ret 
    
    
    通过这个反汇编,我们就能明白为啥无论一个对象是否为nil都会执行了,主要的就是在释放的时候会先判断一下自身是否为空,不为空的时候才会执行释放操作

    所以,建议大家在这种情况下,先将以后要判断的对象初始化为nil,如果不初始化的话,系统分配给对象变量一个不为nil的坏指针,那样后面的判断就失效了,我想我朋友估计
    也是忽略了这一点吧!


  • 相关阅读:
    单元测试的那点事儿
    centos 下载为firefox安装flash插件
    ubuntu lamp(apache+mysql+php) 环境搭建及相关扩展更新
    PHP源代码数组统计count分析
    fgetcsv函数的“陷阱”
    安装phpunit出现could not extract the package.xml file
    Centos Nginx + Svbversion配置安装
    双系统XP和ubuntu,升级ubuntu出现no such device grub rescue
    centos5 源码安装Nginx + mysql + apache + php
    再谈fgetcsv之在ubuntu10.10下不能解析中文的问题
  • 原文地址:https://www.cnblogs.com/DxSoft/p/1737116.html
Copyright © 2020-2023  润新知