Переменная, возможно, не была инициализирована. Могу ли я включить это предупреждение для строки? - PullRequest
7 голосов
/ 24 апреля 2011

Когда я компилирую этот код

{$WARNINGS ON}
function Test(s: string): string;
var
  t: string;
  d: double;
begin
  if s = '' then begin
    t := 'abc';
    d := 1;
  end;

  Result := t + FloatToStr(d);
end;

Я получаю предупреждение "Переменная 'd', возможно, не была инициализирована", но я не получаю того же предупреждения для переменной "t". Это кажется противоречивым. Этот код является лишь простым примером для отображения предупреждений компилятора, но я только что нашел ошибку в моем живом коде, которая была бы обнаружена предупреждением времени компиляции для неинициализированных строковых переменных. Можно ли как-то включить это предупреждение в Delphi 6? Или в более новой версии Delphi?

Ответы [ 2 ]

12 голосов
/ 24 апреля 2011

Нет, для этого нет переключателя.Предупреждение не появляется, потому что строка является управляемым типом компилятора и всегда инициализируется компилятором.

3 голосов
/ 24 апреля 2011

Да: -)

Используйте короткие шорты или pChars

{$WARNINGS ON}
function Test: String;
var
  p: pChar;
  d: double;
begin
  Result := p + FloatToStr(d);
end;
//This code will give a warning.

Серьезно

Нет, нормальный Delphiстроки и короткие строки автоматически инициализируются как '' (пустая строка).Короткие струны живут в стеке и не нуждаются в очистке.Другие строки являются так называемыми «управляемыми» типами и автоматически удаляются, когда они больше не используются с использованием подсчета ссылок.

PChars, хорошие новости
pChars - это просто указатели.Delphi не управляет ими.
Однако Delphi делает автоматически конвертирует их в строки и наоборот.

pChars плохие новости
Если вы преобразуете pChar в строку Delphi копирует содержимое pChar в строку, и вы по-прежнему несете ответственность за уничтожение pChar.
Также обратите внимание, что это копирование занимает время, и если вы это делаетеэто сильно замедлит ваш код.

Если вы преобразуете строку в pChar Delphi даст вам указатель на адрес, в котором находится строка. И !!Delphi перестанет управлять строкой.Вы все еще можете присвоить значения строке, но она больше не будет автоматически расти.

From: http://www.marcocantu.com/epascal/English/ch07str.htm

Следующий код не будет работать должным образом:

procedure TForm1.Button2Click(Sender: TObject);
var
  S1: String;
begin
  SetLength (S1, 100);
  GetWindowText (Handle, PChar (S1), Length (S1));
  S1 := S1 + ' is the title'; // this won't work
  Button1.Caption := S1;
end;

Эта программа компилируется, но когда вы ее запустите, вас ждет сюрприз: заголовок кнопки будет иметь исходный текст заголовка окна без текста константной строки, которую вы добавили к нему.Проблема в том, что когда Windows записывает в строку (в рамках вызова API GetWindowText), она не устанавливает длину длинной строки Pascal должным образом.Delphi все еще может использовать эту строку для вывода и может выяснить, когда она заканчивается, ища нулевой терминатор, но если вы добавите дополнительные символы после нулевого терминатора, они будут вообще пропущены.

Как мы можем это исправитьпроблема?Решение состоит в том, чтобы сказать системе преобразовать строку, возвращаемую вызовом API GetWindowText, обратно в строку Паскаля.Однако, если вы напишите следующий код:

S1 := String (S1);

, система проигнорирует его, потому что преобразование типа данных обратно в себя - бесполезная операция.Чтобы получить правильную длинную строку Паскаля, вам нужно переписать строку в PChar и позволить Delphi правильно преобразовать ее обратно в строку:

S1 := String (PChar (S1));

На самом деле, вы можете пропустить преобразование строки, потому что PChar-преобразования в строку в Delphi выполняются автоматически.Вот окончательный код:

procedure TForm1.Button3Click(Sender: TObject);
var
  S1: String;
begin
  SetLength (S1, 100);
  GetWindowText (Handle, PChar (S1), Length (S1));
  S1 := String (PChar (S1));
  S1 := S1 + ' is the title';
  Button3.Caption := S1;
end;

Альтернативой является сброс длины строки Delphi, используя длину строки PChar, путем записи:

SetLength (S1, StrLen (PChar (S1)));
...