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

в этом примере

procedure foobar;
var tab:array of integer;
begin
  setlength(tab,10);
end;

массив уничтожен или утечка памяти?


person Azarien    schedule 24.06.2010    source источник
comment
Хотя это может и не протекать, вам действительно следует освободить свои собственные переменные. Сделайте SetLength (вкладка, 0); это одна лишняя строка. Если вы беспокоитесь об этом, заключите его в блок try / finally.   -  person Vivian Mills    schedule 25.06.2010
comment
Я не могу согласиться с этим советом, @Ryan. Вы тоже вручную очищаете все строковые переменные? Когда я вижу, как код присваивает значения переменным, которые никогда больше не используются, это говорит мне, что программист на самом деле не понимает, как работает язык. В частности, компилятор уже помещает блок try-finally вокруг тела функции, чтобы гарантировать, что переменная динамического массива будет очищена. Вставить один из них - это излишне.   -  person Rob Kennedy    schedule 25.06.2010
comment
@ Райан, это неправильно. Вызов SetLength - это пустая трата нажатий клавиш и ненужного вызова функций во время выполнения. Динамические массивы управляются компилятором и автоматически освобождаются, когда они выходят за пределы области видимости.   -  person Ken White    schedule 25.06.2010
comment
Память для массива освобождается компилятором, но массив объектов, на которые ссылается динамический массив, все равно должен быть освобожден, если этот массив концептуально владеет ими. Измените приведенный выше код с tab: array of integer на tab: array of TObject, и вдруг у вас появится возможность утечки.   -  person Warren P    schedule 25.06.2010
comment
@Rob, так ты хочешь сказать, что это пустая трата времени делать какое-либо защитное кодирование или только для данного примера? Я бы предпочел, как вы выразились, переборщить и убедиться, что знаю, что происходит, чем делать предположения и ошибаться. Прочитав ваш комментарий, я пошел, чтобы узнать, как правильно с этим справиться, и использование SetLength, равного 0, может быть не лучшим решением, но, согласно файлу справки, вы должны либо назначить nil, либо использовать функцию Finalize.   -  person Vivian Mills    schedule 25.06.2010
comment
@Ken, ты тоже не сторонник защитного программирования? Так что это дополнительный вызов, большое дело. Назначение Nil или вызов Finalize в соответствии с рекомендациями Help по-прежнему выходит за рамки того, что вы отстаиваете. Как указал Уоррен П., что, если приведенный выше пример не был массивом int, а массивом объектов? Все, что я говорю, это то, что вы должны убирать за собой, чтобы вы точно знали, что происходит, независимо от того, как выглядит точный код.   -  person Vivian Mills    schedule 25.06.2010
comment
@Ryan, присвоение nil, вызов Finalize и установка нулевой длины - все это эквивалентные способы освобождения динамического массива. И они все не нужны, когда массив выходит за пределы области видимости, потому что это еще один способ освободить динамический массив. Справка не говорит об этом явно, потому что это подразумевает, что динамические массивы используют тот же метод подсчета ссылок, что и длинные строки. Защитное программирование - это хорошо, но лучше, когда вы защищаетесь от вещей, которые могут произойти на самом деле.   -  person Rob Kennedy    schedule 25.06.2010
comment
@ Райан, комментарий Уоррена не имеет значения. Разрешение уничтожить массив, когда он выходит за пределы области видимости, не освободит объекты, но и не очистит или завершит массив вручную. Независимо от типа элемента массива правила уничтожения массива не меняются; фактически, компилятор даже генерирует идентичный код (за исключением значения PTypeInfo, которое он передает в DynArrayClear).   -  person Rob Kennedy    schedule 25.06.2010


Ответы (2)


Память освобождена. (То есть утечки памяти нет!)

person Andreas Rejbrand    schedule 24.06.2010
comment
Также освобождаются элементы, если они тоже управляются компилятором (dyn массивы, строки, intf, записи с такими типами и т. Д.). - person alex; 25.06.2010
comment
Для вкладки: массив целых чисел все освобождено. Для tab: array of TObject или любого другого класса вы должны освободить объекты самостоятельно. - person Warren P; 25.06.2010
comment
Верно, @Warren, но это не имеет ничего общего с массивом. Тот же совет применим и к обычному скаляру. Объекты нужно освобождать; целые числа нет. - person Rob Kennedy; 25.06.2010

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

person Alan Clark    schedule 24.06.2010
comment
Есть только две причины, по которым его не освободят. Либо вы делаете что-то страшное с указателями, которые нарушают подсчет ссылок, либо массив принадлежит объекту или записи, которая также протекает. - person Mason Wheeler; 25.06.2010
comment
Я знаю, почему-то было что-то еще, из-за чего он не работал автоматически. Хотел бы я еще иметь пример, чтобы доказать это! Но я этого не делаю. - person Alan Clark; 25.06.2010
comment
Это было бы ошибкой в ​​генераторе кода компилятора. А может это был нитевар? В справке четко указано, что управляемый тип, используемый в качестве переменных потоков, не освобождается автоматически, и вам нужно сделать это вручную. - person Ken Bourassa; 25.06.2010
comment
Это не было тредеваром, я никогда ими не пользовался. Это был просто массив двойников, который был полем класса, FastMM обнаружил утечку. Это было в Delphi 7. - person Alan Clark; 25.06.2010