![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Access violation при Finalize(массив) [D6, D7, WinXP]
Death_R © (2010-05-18 16:04:00)Есть такое:
TZp = record
Sum: Currency;
kod: string[10];
end;
TStat = record
fname: string[8];
Peopl: Word;
Dan: array of TZp;
cbIsPrn: TCheckBox;
lCount: TLabel;
end;
...
private
AStat: array of TStat;
...
далее идут операции создания и заполнения массива, работа с ним. Если ничего с массива не удалять и сделать Finalize(AStat)то все нормально. НО!!! Если сделать:
//Удаление с массива элементов по некому условию
nfile := 'ля-ля-ля';
start := -1; stop := -1;
//вычисление с какого и по какой элемент нужно удалить
for i := 0 to length(AStat)-1 do
begin
if (start = -1)and(nfile = AStat[i].fname) then start := i;
if (start >= 0)and(nfile <> AStat[i].fname) then stop := i;
if stop > -1 then break;
if nfile = AStat[i].fname then
begin
Finalize(AStat[i].Dan);
Finalize(Astat[i]);
end;
end;
//если с до конца нужно удалить, то просто обрезаем массив
if stop = -1 then SetLength(AStat, start+1)
else
begin
System.Move(AStat[stop], //с какого начинаем перемещение
AStat[start], //на какое место
(Length(AStat) - stop + 1) * SizeOf(AStat[stop])); //размер перемещаемого
SetLength(AStat, Length(AStat) - (stop - start)+1);
end;
после удаления вызывается Finalize(AStat) и сразу же вілетает ошибка Access violation at ...
Sapersky (2010-06-18 18:54:00) [1]MOVE, вопреки своему названию, не перемещает, а копирует. "Старые" данные при этом остаются (по крайней мере частично), и компилятор при уничтожении массива пытается их автоматически финализировать - т.е. фактически финализировать одно и то же 2 раза, поскольку у нас теперь 2 копии - отсюда AV. Поэтому старую копию нужно обнулить. Только не финализом, а FillChar, поскольку мы не уничтожаем данные, а просто затираем лишнюю с т.з. компилятора копию.
Death_R (2010-06-18 18:27:00) [2]
> Суслик_ © (21.05.10 01:10) [6]
>
> Я тебе отвечу, так, если ты что-то в массиве переместил,
> то ты должен обнилить (используй FillChar) в той части
> откуда ты перенес значения с управляемым временим жизни.
> В твоем случае такое значение одно - это Dan.
Проблема в том, что при перемещении MOVE в область памяти записываются адреса (в моем случае - адресс первого элемента массива Dan). Так вот когда сделать обнуление, то все данные этого массива обнулятся, да впрочем и всего остального!! Это я пробывал и так получилось. Поэтому просто делается освобождение памяти посредством обрезания массива.
Death_R (2010-06-18 18:21:00) [3]Отвечаю на некоторые замечания:
По поводу Finalize(AStat[i]) - это я экспериментировал.
По поводу перемещений MOVE: когда убираю с записи Dan (т.е. вложенный динамический массив) и кусочек кода
if nfile = AStat[i].fname then
begin
Finalize(AStat[i].Dan);
Finalize(Astat[i]);
end;
то все прекрастно работает, а вот при присутствии Dan не пашит!!!!
Суслик_ (2010-05-21 01:10:00) [4]Автор, ты поступаешь нехорошо - ты даешь код, в котором надо разбирать.
Код плохой, код неполный.
У тебя вопрос по finalize?
Я тебе отвечу, так, если ты что-то в массиве переместил, то ты должен обнилить (используй FillChar) в той части откуда ты перенес значения с управляемым временим жизни. В твоем случае такое значение одно - это Dan.
Т.е. тебе нужно сделать так, чтобы - если ты перенес из одной ячейки массива в другую твой Dan, то исходный Dan ты должен обнулить. В противном случае Finalize на весь массив даст AV.
Я тебе готов помочь разобраться, но код нужен более полный.
Попытайся вычленить полноценный код, который сам по себе дает AV.
Sapersky (2010-05-19 11:22:00) [5]Наоборот, можно использовать Move с managed-типами при условии грамотного применения Finalize, см. TStringList.Delete.
Как вариант, можно вручную поприбивать все вложенные managed-переменные. Особенно если переменная всего одна на элемент массива, как в случае TStringList или у автора.
Германн (2010-05-19 02:07:00) [6]Если я не ошибаюсь, то процедура Move абсолютно не совместима с Finalize. То бишь с типами, с контролируемым временем жизни.
Loginov Dmitry (2010-05-18 22:24:00) [7]
> Finalize(Astat[i]);
Это еще что такое? И как после этого не будет ошибок?
_Юрий (2010-05-18 19:20:00) [8]Почему бы не сделать на списке вместо массива, и объектах вместо записей?
Код удаления займет ровно одну строку, и косяки с финализацией в принципе не возникнут
Death_R (2010-05-18 17:36:00) [9]Небольшое исправление
System.Move(AStat[stop1],
AStat[start1],
(Length(AStat) - stop1) * SizeOf(AStat[stop1]));
SetLength(AStat, Length(AStat) - stop1 + start1);