Форум: "Основная";
Текущий архив: 2011.12.11;
Скачать: [xml.tar.bz2];
ВнизAccess violation при Finalize(массив) Найти похожие ветки
← →
Death_R © (2010-05-18 16:04) [0]Есть такое:
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 ...
← →
Death_R © (2010-05-18 17:36) [1]Небольшое исправление
System.Move(AStat[stop1],
AStat[start1],
(Length(AStat) - stop1) * SizeOf(AStat[stop1]));
SetLength(AStat, Length(AStat) - stop1 + start1);
← →
_Юрий © (2010-05-18 19:20) [2]Почему бы не сделать на списке вместо массива, и объектах вместо записей?
Код удаления займет ровно одну строку, и косяки с финализацией в принципе не возникнут
← →
Loginov Dmitry © (2010-05-18 22:24) [3]
> Finalize(Astat[i]);
Это еще что такое? И как после этого не будет ошибок?
← →
Германн © (2010-05-19 02:07) [4]Если я не ошибаюсь, то процедура Move абсолютно не совместима с Finalize. То бишь с типами, с контролируемым временем жизни.
← →
Sapersky (2010-05-19 11:22) [5]Наоборот, можно использовать Move с managed-типами при условии грамотного применения Finalize, см. TStringList.Delete.
Как вариант, можно вручную поприбивать все вложенные managed-переменные. Особенно если переменная всего одна на элемент массива, как в случае TStringList или у автора.
← →
Суслик_ © (2010-05-21 01:10) [6]Автор, ты поступаешь нехорошо - ты даешь код, в котором надо разбирать.
Код плохой, код неполный.
У тебя вопрос по finalize?
Я тебе отвечу, так, если ты что-то в массиве переместил, то ты должен обнилить (используй FillChar) в той части откуда ты перенес значения с управляемым временим жизни. В твоем случае такое значение одно - это Dan.
Т.е. тебе нужно сделать так, чтобы - если ты перенес из одной ячейки массива в другую твой Dan, то исходный Dan ты должен обнулить. В противном случае Finalize на весь массив даст AV.
Я тебе готов помочь разобраться, но код нужен более полный.
Попытайся вычленить полноценный код, который сам по себе дает AV.
← →
Death_R © (2010-06-18 18:21) [7]Отвечаю на некоторые замечания:
По поводу Finalize(AStat[i]) - это я экспериментировал.
По поводу перемещений MOVE: когда убираю с записи Dan (т.е. вложенный динамический массив) и кусочек кодаif nfile = AStat[i].fname then
begin
Finalize(AStat[i].Dan);
Finalize(Astat[i]);
end;
то все прекрастно работает, а вот при присутствии Dan не пашит!!!!
← →
Death_R © (2010-06-18 18:27) [8]
> Суслик_ © (21.05.10 01:10) [6]
>
> Я тебе отвечу, так, если ты что-то в массиве переместил,
> то ты должен обнилить (используй FillChar) в той части
> откуда ты перенес значения с управляемым временим жизни.
> В твоем случае такое значение одно - это Dan.
Проблема в том, что при перемещении MOVE в область памяти записываются адреса (в моем случае - адресс первого элемента массива Dan). Так вот когда сделать обнуление, то все данные этого массива обнулятся, да впрочем и всего остального!! Это я пробывал и так получилось. Поэтому просто делается освобождение памяти посредством обрезания массива.
← →
Sapersky (2010-06-18 18:54) [9]MOVE, вопреки своему названию, не перемещает, а копирует. "Старые" данные при этом остаются (по крайней мере частично), и компилятор при уничтожении массива пытается их автоматически финализировать - т.е. фактически финализировать одно и то же 2 раза, поскольку у нас теперь 2 копии - отсюда AV. Поэтому старую копию нужно обнулить. Только не финализом, а FillChar, поскольку мы не уничтожаем данные, а просто затираем лишнюю с т.з. компилятора копию.
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2011.12.11;
Скачать: [xml.tar.bz2];
Память: 0.47 MB
Время: 0.004 c