Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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.003 c
4-1242382646
Игорь
2009-05-15 14:17
2011.12.11
Функция IsProcessInJob в Windows 2000


2-1314552284
Gu
2011-08-28 21:24
2011.12.11
Dll


15-1313174177
Anatoly Podgoretsky
2011-08-12 22:36
2011.12.11
induc.2


4-1251202011
ivanoff
2009-08-25 16:06
2011.12.11
прочесть что написано в Label другого приложния


2-1314685531
Patrick1968
2011-08-30 10:25
2011.12.11
Проверка состояния сервиса Windows





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский