Delphi TStringList Free Causes Exception

Consider this short Delphi procedure:

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; 

When I run this, Delphi 3, with x = ``, so field_list is never created,

  • Why is field_list <> NIL ?
  • - objects not initialized as NIL ?
  • if it is not NIL , what is it?
  • and if it's not assigned, not NIL , how do you know if it has Free ? Assigned function does not tell me: if Assigned(an_object) equivalent to if an_object = NIL
+4
source share
2 answers

The problem is that if x = '' , finally all the same. Since field_list initialized only when x <> '' , this is a random memory cell before this point, because it is an uninitialized local variable. A random value allows you to call field_list.free , because it is not nil . (Delphi does not initialize local variables (declared inside a function or procedure).

 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; 

You do not need to test <> nil (as others pointed out in the comments) if you structure your code correctly.

 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; 

(If you included hints and warnings, the compiler would tell you that field_list may not have been initialized , which would help you solve this yourself.)

+8
source

So, now that I know that objects local to a procedure or function are not NIL initialized, I revised the code as follows:

 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; 

Alternatively, I could put try..finally block only the string list create and {do some stuff..} , but I like to protect the whole procedure; for example, if it was a try..except block, where I am concerned that the if x test might fail. Too bad that Delphi does not initialize local variable objects with zero.

0
source