Мне пришла в голову необычная мысль, может я туплю, но проясните пожалуйста.
Предположим, у нас есть такой код:
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;
"Ты должен сделать добро из зла, потому что его больше не из чего сделать". АБ Стругацкие.
Здравствуйте, 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 динамический массив передаётся как параметр, происходит передача указателя или указателя на указатель?
Да. Любой параметр передающийся по ссылке на низком уровне является указателем.
"Ты должен сделать добро из зла, потому что его больше не из чего сделать". АБ Стругацкие.
Здравствуйте, Khimik, Вы писали:
K> R>В Delphi есть т.н. управляемые типы к которым относятся строки, дин.массивы, интерфейсы, варианты и записи с перегруженными операторами инициализации/финализации. Их начальную инициализацию гарантирует компилятор. В пролог функции добавляется код обспечивающий обнуление соответствующих областей памяти.
K> Понятно, а если динамический массив является свойством record-а?
В любом случае. Однако, если запись выделяется динамически, то для нее следует использовать New/Dispose вместо GetMem/FreeMem т.к. первые гарантируют корректную инициализацию/финализацию полей управляемых типов.