When you allocate an object reference on the stack, it is filled with random values (i.e. the previous values on the stack - which may be nil in some border cases). This is by design.
In order to check if the variable is initialized, you'll have first to set it manually to nil. This is a very fast assignment.
A typical code pattern may be:
procedure TForm1.Button1Click(Sender: TObject);
var
  sVariable : TStringList;
begin
  sVariable := nil; // initialize explicitely
  try
    (...) // in this hidden part sVariable may be instantiated
    if not Assigned(sVariable) then // instantiate if not already done
      sVariable:= TStringList.Create; 
    (...)
  finally
    sVariable.Free; // will do nothing if sVariable=nil
  end;
end; 
Note that in the above code, I've included a (mandatory IMHO) try...finally block to release the memory. If sVariable was not allocated, it is still nil, and in this case sVariable.Free will do nothing. It is an usual best practice pattern in Delphi.