Локальная переменная TStringList не инициализирована в ноль - почему? - PullRequest
2 голосов
/ 04 ноября 2011

Я использую этот код, чтобы проверить, создан ли TStringList или нет:

procedure TForm1.Button1Click(Sender: TObject);
var

  sVariable : TStringList;
begin
   if not Assigned(sVariable) then
   sVariable:= TStringList.Create;
end; 

Но условие False всегда, почему это происходит? Как проверить, создан объект TStringList или нет?

P.s. Мне известно о подобном вопросе, который я задавал, я попробовал опубликованное в нем решение, но оно не работает для меня.

Ответы [ 5 ]

15 голосов
/ 04 ноября 2011

Когда вы выделяете ссылку на объект в стеке, она заполняется случайными значениями (то есть предыдущими значениями в стеке - которые могут быть равны нулю в некоторых случаях границы). Это по замыслу.

Чтобы проверить, инициализирована ли переменная, вам сначала нужно будет установить ее вручную на nil. Это очень быстрое задание.

Типичный шаблон кода может быть:

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; 

Обратите внимание, что в вышеприведенном коде я включил (обязательно IMHO) try...finally блок для освобождения памяти. Если sVariable не был выделен, это все равно nil, и в этом случае sVariable.Free ничего не сделает. Это обычный шаблон лучших практик в Delphi.

8 голосов
/ 04 ноября 2011

Можно предположить, что объект не создан и переменная инициализирована с мусором (поскольку это локальная переменная).Просто создайте свой StringList и все в порядке.

7 голосов
/ 04 ноября 2011

Прежде всего: код, который вы опубликовали, не имеет смысла. Поскольку sVariable является локальной переменной, она всегда неинициализирована. Но в отличие от переменных в объектной области, неинициализированный не означает, что он равен нулю. Delphi не будет устанавливать локальные переменные в ноль. Таким образом, sVariable содержит полностью случайное значение. Функция Assigned () только проверяет, имеет ли значение значение nil, но не указывает, что оно указывает на действительный экземпляр объекта.

3 голосов
/ 04 ноября 2011

После того, как вы обновите вопрос, то, что я вижу, кажется вполне нормальным.

Когда вы определяете переменную объекта (sVariable), она не инициализируется, что вы должны сделать с помощью Createконструктор.В этом случае вам даже не нужно проверять, существует ли он или нет.

procedure TForm1.Button1Click(Sender: TObject);
var
  sVariable : TStringList;
begin
   sVariable:= TStringList.Create;
   //Work with the stringlist e.g add items:
   sVariable.Add('Blah');
   //Make sure it finally gets freed 
   sVariable.Free;
end; 
3 голосов
/ 04 ноября 2011

Вы можете сделать это напрямую, потому что это локальная переменная

procedure TForm1.Button1Click(Sender: TObject);
var
  sVariable : TStringList;
begin
  sVariable:= TStringList.Create;
end;
...