Как сделать локальный массив постоянным? - PullRequest
1 голос
/ 31 января 2012

У меня есть процедура обратного вызова:

type
  TInitCallback = procedure (var Data: Pointer);

Идея состоит в том, что после инициализации Data может указывать на что угодно.

Я пытался назначить эту процедуру для обратного вызова иinit Data таким образом, чтобы он указывал на вновь созданный массив:

type
  TBoolArray = array of Boolean;

procedure InitData(var Data: Pointer);
var
  BoolArray: TBoolArray;
  i: Integer;
begin
  SetLength(BoolArray, 10);
  for i := 0 to Length(BoolArray) - 1 do
    BoolArray[i] := False;
  Data := BoolArray;
end;

Однако я не уверен, что счетчик ссылок увеличивается для массива при присваивании: Data := BoolArray;.Другими словами - я не уверен, что массив остается в памяти после выхода из процедуры или он был освобожден?

Потому что позже при выполнении программы, когда я изменяю данные в какой-то другой структуре (записи, котораяне имеет ничего общего с этим массивом), это изменение вносит изменения в ранее выделенный массив (Data).

Одним из объяснений этого было бы то, что память для массива была освобождена при выходе из обратного вызова и повторно использована длязапись.

Итак, массив остается выделенным после выхода из обратного вызова InitData или нет?А если нет, то как заставить его остаться выделенным.Обратите внимание, что я не хочу менять подпись моего обратного вызова, я не могу вводить какие-либо новые параметры или изменять их в функции.

Спасибо.

1 Ответ

5 голосов
/ 31 января 2012

Вы правы, полагая, что счетчик ссылок динамического массива не увеличивается при назначении на Data.Это означает, что локальный массив выходит из области видимости, когда возвращается InitData.Таким образом, ваш код не работает.

Самое простое решение - изменить определение TInitCallback на использование динамического массива, и тогда механизм ссылок будет управлять временем жизни за вас.Так как вы не хотите менять интерфейс, у вас есть (по крайней мере) следующие опции:

  1. Сделать BoolArray глобальной переменной.Это будет работать только в том случае, если в вашем приложении есть только один экземпляр.
  2. Измените тип BoolArray на ^TBoolArray и используйте New, чтобы выделить его в куче.Вам также необходимо добавить еще одну процедуру, которая освобождает массив с помощью вызова Dispose.
  3. Очень похоже на вариант 2, заключая массив в класс.Экземпляры класса можно безопасно хранить в указателях.Снова вам понадобится другая функция для удаления экземпляра класса путем вызова Free.
...