2013-03-16 69 views
4

考慮這短短的Delphi程序:當我運行這德爾福的TStringList免費導致異常

procedure TfrmXQuery.FieldListFillFromDefault; 
var 
    field_list: TStringList; 
begin 
    try 
    if x <> '' then begin 
     field_list := TStringList.Create; 
     {do some stuff with field_list} 
    end; 
    finally 
    if field_list <> NIL then 
    begin 
     field_list.Free; 
    end; 
    end; 
end; 

,德爾福3,其中x = '',因此永遠不會創建FIELD_LIST,

  1. 爲什麼field_list <> NIL
  2. 是未初始化爲NIL的對象?
  3. 如果不是NIL這是什麼?
  4. 如果是未分配而不是NIL我怎麼知道是否要Free呢?該Assigned功能並沒有告訴我:if Assigned(an_object)if an_object = NIL
+0

絕對沒有必要在免費之前檢查指定的參考。免費已經這樣做,如果分配調用Destroy。這就是爲什麼你不應該叫Destroy – 2013-03-16 03:53:19

+1

沒有編譯器警告你這個代碼?切勿忽略編譯器診斷。 – 2013-03-16 04:34:03

+0

此答案將對您有所幫助:http://stackoverflow.com/questions/8548843/why-should-i-not-use-if-assigned-before-using-or-freeing-things/8550628#8550628 – 2013-03-16 07:33:17

回答

8

等價的問題是if x = '',將finally發生反正。由於field_list僅在x <> ''時才被初始化,因此它是一個隨機內存位置,因爲它是一個未初始化的局部變量。隨機值允許調用field_list.free,因爲它不等於nil。 (德爾福未初始化的局部變量(這些函數或過程)中聲明。)

var 
    somevar: sometype;  
begin 
    // at this point, somevar is just a chunk of memory that 
    // holds whatever happens to be in that chunk 
    somevar := nil;   // now somevar = a specific value you can test 

    // other code 
end; 

你不應該來測試<> nil(如別人的意見所指出的那樣),如果你正確地組織你的代碼。

procedure TfrmXQuery.FieldListFillFromDefault; 
var 
    field_list : TStringList; 
begin 
    if x <> '' then 
    begin 
    field_list := TStringList.Create; 
    try 
     {do some stuff with field_list} 
    finally 
     field_list.Free; 
    end; 
    end; 
end; 

所以,現在我知道(如果你打開提示和警告,編譯器會告訴你,field_list may not have been initialized,這會幫助你解決這個你自己。)

+0

那裏不需要'if field_list <> NIL'。 'TObject.Free'已經爲此測試 - 實際上它是它的全部目的。所有這些都是說'if field_list <> NIL then field_list <> NIL then field_list.Destroy;'見http://docwiki.embarcadero.com/Libraries/XE2/en/System.TObject.Free – 2013-03-16 03:59:55

+0

@Gerry:很好的接收。我錯過了在兩個代碼片段中刪除它們。謝謝。 :-) – 2013-03-16 04:17:23

+1

「Delphi 3沒有初始化局部變量」沒有Delphi的版本。 – 2013-03-16 07:34:31

0

是局部對象過程或函數不被初始化爲NIL我修改了代碼如下:

procedure TfrmXQuery.FieldListFillFromDefault; 
var 
    field_list: TStringList; 
begin 
    try 
    field_list := NIL; 
    if x <> '' then begin 
     field_list := TStringList.Create; 
     {do some stuff with field_list} 
    end; 
    finally 
    field_list.Free; 
    end; 
end; 

我也可以把try..finally其周圍只是字符串列表創建和代碼但我喜歡保護整個程序;例如,如果它是try..except塊,我擔心if x測試可能會失敗。 Delphi不會將局部變量對象初始化爲零。

+0

初始化爲零會浪費。在if裏面移動try/finally。或者更好的是,在開始時將if轉換爲警衛權:如果x =''則退出;此外,這不回答問題。 – 2013-03-16 22:45:49

+0

或者我可以把try..finally塊放在字符串列表create和{do some stuff ..}代碼中,但我喜歡保護整個過程;例如,如果它是try..except塊,我擔心if x測試可能會失敗。 Delphi不會將局部變量對象初始化爲零。 – 2013-03-17 06:33:05

+1

是的,我第一次看了那篇文章。使用非標準的try/finally只會讓讀者不得不更加認真地考慮代碼。不要這樣做。 – 2013-03-17 07:53:02