zoukankan      html  css  js  c++  java
  • 一个小问题引发的论证思考

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

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

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

    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的坏指针,那样后面的判断就失效了,我想我朋友估计
    也是忽略了这一点吧!


  • 相关阅读:
    Entity SQL 初入
    ObjectQuery查询及方法
    Entity Framework 的事务 DbTransaction
    Construct Binary Tree from Preorder and Inorder Traversal
    Reverse Linked List
    Best Time to Buy and Sell Stock
    Remove Duplicates from Sorted Array II
    Reverse Integer
    Implement Stack using Queues
    C++中const限定符的应用
  • 原文地址:https://www.cnblogs.com/DxSoft/p/1737116.html
Copyright © 2011-2022 走看看