Why are Delphi objects assigned even after calling .Free?

If you use sl.Free, the object is freed but the variable sl still points to the now invalid memory.

Use FreeAndNil(sl) to both free the object and clear the pointer.

By the way, if you do:

var
  sl1, sl2: TStringList;
begin
  sl1 := TStringList.Create;
  sl2 := sl1;
  FreeAndNil(sl1);
  // sl2 is still assigned and must be cleared separately (not with FreeAndNil because it points to the already freed object.)
end;




procedure TObject.Free;
asm
    TEST    EAX,EAX
    JE      @@exit              // Jump to exit if pointer is nil.
    MOV     ECX,[EAX]           
    MOV     DL,1
    CALL    dword ptr [ECX].vmtDestroy  // Call cleanup code (and destructor).
@@exit:
end;

Delphi VCL 'objects' are actually always pointers to objects, but this aspect is typically hidden from you. Just freeing the object leaves the pointer dangling around, so you should use FreeAndNil instead.

The "Mysterious Assembler" translates roughly to:

if Obj != NIL then
  vmtDestroy(obj);  // which is basically the destructor/deallocator.

Because Free checks for NIL first, it's safe to call FreeAndNil multiple times...