Как пропустить строку в Delphi

Путем я делаю это, у меня есть пустой репозиторий Мерзавца на моем сервере развертывания, где я продвигаю изменения. Тогда я вхожу в систему сервера развертывания, изменяюсь на фактический каталог документов веб-сервера и делаю получение по запросу мерзавца. Я не использую рычагов, чтобы попытаться сделать это автоматически, которое походит на большую проблему, чем это стоит.

11
задан Jim McKeeth 15 July 2009 в 16:45
поделиться

4 ответа

На самом деле, передача строки как CONST или не const одинакова с точки зрения счетчика ссылок в Delphi 2007 и 2009. Был случай, когда строка была передана как CONST, вызывала нарушение доступа. Вот проблема первая

type
  TFoo = class
    S: string;
    procedure Foo(const S1: string);
  end;

procedure TFoo.Foo(const S1: string);
begin
  S:= S1; //access violation
end;

var
  F: TFoo;
begin
  F:= TFoo.create;
  try
    F.S := 'S';
    F.Foo(F.S);
  finally
    F.Free;
  end;
end.
2
ответ дан 3 December 2019 в 08:56
поделиться

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

var
  Global: string;

procedure One(const Arg: string);
begin
  Global := '';

  // Oops. This is an invalid reference now. Arg points to
  // what Global used to refer to, which isn't there anymore.
  writeln(Arg);
end;

procedure Two;
begin
  Global := 'foo';
  UniqueString(Global);
  One(Global);
  Assert(Global = 'foo', 'Uh-oh. The argument isn''t really const?');
end;

Здесь Аргумент One объявлен как const, поэтому предположительно он не изменится. Но затем Один обходит это, изменяя фактический параметр вместо формального. Процедура Two "знает", что аргумент One является const, поэтому он ожидает, что фактический параметр сохранит свое исходное значение. Утверждение не выполняется.

Строка не просочилась, но этот код демонстрирует, как можно получить висящую ссылку для строки. Arg - это локальный псевдоним Global . Хотя мы изменили Global , значение Arg осталось нетронутым, и поскольку оно было объявлено как const, счетчик ссылок строки не увеличивался при входе в функцию. При переназначении Global счетчик ссылок сбрасывается до нуля, и строка уничтожается. Объявление Arg как var вызовет ту же проблему; передача по значению решит эту проблему. (Вызов UniqueString предназначен только для того, чтобы убедиться, что строка подсчитывается по ссылкам. В противном случае, это может быть строковый литерал без подсчета ссылок.) Все типы, управляемые компилятором, подвержены этой проблеме; простые типы невосприимчивы.

Единственный способ утечки строки - это рассматривать ее как нечто иное, чем строка, или использовать функции управления памятью, не поддерживающие типы. Ответ Мги описывает, как обрабатывать строку как нечто отличное от строки, используя FillChar для затирания строковой переменной. Функции памяти, не поддерживающие типы, включают GetMem и FreeMem . Например:

type
  PRec = ^TRec;
  TRec = record
    field: string;
  end;

var
  Rec: PRec;
begin
  GetMem(Rec, SizeOf(Rec^));
  // Oops. Rec^ is uninitialized. This assignment isn't safe.
  Rec^.field := IntToStr(4);
  // Even if the assignment were OK, FreeMem would leak the string.
  FreeMem(Rec);
end;

Есть два способа исправить это. Один - вызвать Initialize и Finalize :

GetMem(Rec, SizeOf(Rec^));
Initialize(Rec^);
Rec^.field := IntToStr(4);
Finalize(Rec^);
FreeMem(Rec);

Другой - использовать функции, поддерживающие типы:

New(Rec);
Rec^.field := IntToStr(4);
Dispose(Rec);
4
ответ дан 3 December 2019 в 08:56
поделиться

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

Если вы вызываете FillChar () для записи, содержащей строки, вы перезаписываете счетчик ссылок и адрес динамически выделяемой памяти с нулями. Если строка не пуста, это приведет к утечке памяти. Чтобы решить эту проблему, необходимо вызвать Finalize () для записи перед очисткой памяти, которую она занимает.

К сожалению, вызов Finalize () , когда нет элементов записи, требующих завершения причин подсказка компилятора. Со мной случилось так, что я закомментировал вызов Finalize () , чтобы заглушить подсказку, но позже, когда я добавил к записи строковый член, я пропустил раскомментирование вызова, поэтому произошла утечка. К счастью, я обычно использую диспетчер памяти FastMM в наиболее подробных и параноидальных настройках в режиме отладки, поэтому утечка не осталась незамеченной.

Подсказка компилятора, вероятно, не такая уж хорошая вещь, молча опуская ИМХО, вызов Finalize () , если он не нужен, будет намного лучше.

7
ответ дан 3 December 2019 в 08:56
поделиться

Я думаю это могло быть похоже на то, о чем я думал. Это обратная утечка строки, строка, которая собирается рано:

var
  p : ^String;

procedure InitString;
var
  s, x : String;
begin
  s := 'A cool string!';
  x := s + '. Append something to make a copy in' +
             'memory and generate a new string.';

  p := @x;
end;

begin
  { Call a function that will generate a string }
  InitString();

  { Write the value of the string (pointed to by p) }
  WriteLn(p^); // Runtime error 105!


  { Wait for a key press }
  ReadLn;
end.
0
ответ дан 3 December 2019 в 08:56
поделиться
Другие вопросы по тегам:

Похожие вопросы: