Инициализация стандартных динамических массивов в Delphi
От: Khimik  
Дата: 13.05.22 03:08
Оценка:
Мне пришла в голову необычная мысль, может я туплю, но проясните пожалуйста.
Предположим, у нас есть такой код:

procedure Test;
var
  arr:array of integer;
  val:byte;
begin
  setlength(add,5);
  arr[0]:=val;
end;


Этот код неправильный, поскольку переменная val не инициализирована и при присвоении во второй строке её значение может оказаться каким угодно (в зависимости от чего, что находилось до этого в памяти, которая была выделена под стек). Но тогда возникает вопрос — а как инициируются динамические массивы? Через setlength? Но ведь процедура setlength использует данные о предыдущем состоянии массива: может быть, сначала надо освободить старую память, потом выделить новую, и ещё копировать старые элементы в новую память. Если переменная arr перед setlength не была инициализирована, не может ли получиться, что она будет указывать на какой-то случайный участок в памяти, которую Delphi воспримет как уже существующий массив? Может быть, надо перед setlength прописать arr:=nil?
Вообще поясните, что такое стандартные динамические массивы в Delphi. Это указатель на участок памяти, в котором первые 4 байта заняты интегером, обозначающим число элементов в массиве? Ещё вопрос — если в процедуре через var динамический массив передаётся как параметр, происходит передача указателя или указателя на указатель? Я имею в виду такой код:

procedure Proc(var arr:array of integer);
begin
  arr[0]:=5;  //Ошибки не возникнет?  
end;

var
  arr1:array of integer;
begin
  arr1:=nil;
  setlength(arr1,5);
  Proc(arr1);
end;
"Ты должен сделать добро из зла, потому что его больше не из чего сделать". АБ Стругацкие.
Re: Инициализация стандартных динамических массивов в Delphi
От: rudzuk  
Дата: 13.05.22 08:02
Оценка: 6 (1)
Здравствуйте, Khimik, Вы писали:

K>Но тогда возникает вопрос — а как инициируются динамические массивы? Через setlength? Но ведь процедура setlength использует данные о предыдущем состоянии массива: может быть, сначала надо освободить старую память, потом выделить новую, и ещё копировать старые элементы в новую память. Если переменная arr перед setlength не была инициализирована, не может ли получиться, что она будет указывать на какой-то случайный участок в памяти, которую Delphi воспримет как уже существующий массив? Может быть, надо перед setlength прописать arr:=nil?


В Delphi есть т.н. управляемые типы к которым относятся строки, дин.массивы, интерфейсы, варианты и записи с перегруженными операторами инициализации/финализации. Их начальную инициализацию гарантирует компилятор. В пролог функции добавляется код обспечивающий обнуление соответствующих областей памяти.

K> Вообще поясните, что такое стандартные динамические массивы в Delphi. Это указатель на участок памяти, в котором первые 4 байта заняты интегером, обозначающим число элементов в массиве?


https://docwiki.embarcadero.com/RADStudio/Alexandria/en/Internal_Data_Formats_(Delphi)#Dynamic_Array_Types

K> Ещё вопрос — если в процедуре через var динамический массив передаётся как параметр, происходит передача указателя или указателя на указатель?


Да. Любой параметр передающийся по ссылке на низком уровне является указателем.
avalon/3.0.0
Re[2]: Инициализация стандартных динамических массивов в Delphi
От: Khimik  
Дата: 13.05.22 08:22
Оценка:
Здравствуйте, rudzuk, Вы писали:

R>Здравствуйте, Khimik, Вы писали:


K>>Но тогда возникает вопрос — а как инициируются динамические массивы? Через setlength? Но ведь процедура setlength использует данные о предыдущем состоянии массива: может быть, сначала надо освободить старую память, потом выделить новую, и ещё копировать старые элементы в новую память. Если переменная arr перед setlength не была инициализирована, не может ли получиться, что она будет указывать на какой-то случайный участок в памяти, которую Delphi воспримет как уже существующий массив? Может быть, надо перед setlength прописать arr:=nil?


R>В Delphi есть т.н. управляемые типы к которым относятся строки, дин.массивы, интерфейсы, варианты и записи с перегруженными операторами инициализации/финализации. Их начальную инициализацию гарантирует компилятор. В пролог функции добавляется код обспечивающий обнуление соответствующих областей памяти.


Понятно, а если динамический массив является свойством record-а?
"Ты должен сделать добро из зла, потому что его больше не из чего сделать". АБ Стругацкие.
Re[3]: Инициализация стандартных динамических массивов в Delphi
От: rudzuk  
Дата: 13.05.22 13:29
Оценка:
Здравствуйте, Khimik, Вы писали:

K> R>В Delphi есть т.н. управляемые типы к которым относятся строки, дин.массивы, интерфейсы, варианты и записи с перегруженными операторами инициализации/финализации. Их начальную инициализацию гарантирует компилятор. В пролог функции добавляется код обспечивающий обнуление соответствующих областей памяти.


K> Понятно, а если динамический массив является свойством record-а?


В любом случае. Однако, если запись выделяется динамически, то для нее следует использовать New/Dispose вместо GetMem/FreeMem т.к. первые гарантируют корректную инициализацию/финализацию полей управляемых типов.
avalon/3.0.0
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.