一个小问题引发的论证思考
生活随笔
收集整理的這篇文章主要介紹了
一个小问题引发的论证思考
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
??? 今天,有一個朋友,問了俺一個莫名其妙的問題,問的俺是一愣一愣的,搞了半天愣是沒搞明白。他提問的原話是:
一文件流沒有創建,怎么判斷呢
這個問題還真把我問倒了,我壓根就沒明白這是個啥意思,后來他說了半天之后,我還是沒明白是啥,最后他索性給了一個讓我郁悶了半天的代碼。如下:
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的壞指針,那樣后面的判斷就失效了,我想我朋友估計
也是忽略了這一點吧!
?
轉載于:https://www.cnblogs.com/DxSoft/archive/2010/05/17/1737116.html
總結
以上是生活随笔為你收集整理的一个小问题引发的论证思考的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++ url中文编码处理 编码转为U
- 下一篇: OutputCache各参数的说明【转】