Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2011.12.11;
Скачать: CL | DM;

Вниз

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;
Скачать: CL | DM;

Наверх




Память: 0.49 MB
Время: 0.01 c
15-1313958600
Юрий
2011-08-22 00:30
2011.12.11
С днем рождения ! 22 августа 2011 понедельник


3-1268482847
Grab3
2010-03-13 15:20
2011.12.11
Не применяются изменения в таблице InterBase


15-1314088885
xayam
2011-08-23 12:41
2011.12.11
Переключатель на светильник


2-1314513211
Егорка
2011-08-28 10:33
2011.12.11
Все файлы в папке и подпопках?


2-1314109649
Сергей
2011-08-23 18:27
2011.12.11
Как перехватить исключение Ado?