Форум программистов, компьютерный форум, киберфорум
Наши страницы
Delphi для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 5.00/4: Рейтинг темы: голосов - 4, средняя оценка - 5.00
drka
1 / 1 / 1
Регистрация: 27.05.2013
Сообщений: 65
1

Access Violation при повторном заполнении динамического массива

01.03.2015, 19:47. Просмотров 688. Ответов 7
Метки нет (Все метки)

Здравствуйте, есть код парсинга некоторой информации с сайта.

Кликните здесь для просмотра всего текста

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
type
  RRecord = record
    id:integer;
    img_url:string;
    name_k:string;
    discription:string;
  end;
  TParse = Array of RRecord;
  function ParseVK(url:string):TParse;
implementation
 
  function ParseVK(url:string):TParse;
  var
     mass:TParse
     i:integer;
  begin        
     for i:=0 to 5 do
     begin
         mass[i].id:=i;
         mass[i].img_url:=img_url;
         {...................................................}      
     end;
     Result:=mass;
  end;


Вызываем данную функцию в форме

Кликните здесь для просмотра всего текста

Delphi
1
2
3
4
5
6
7
8
var
   massive:TParse;
procedure TForm1.Button1Click(Sender: TObject);
begin
  if length(massive)<>0 then massive:=nil;
  massive:=ParseVK(Edit1.Text);
  ShowMessage(massive[1].name_k);        
end;


После нажатия кнопки появляется ShowMessage с спаршенной информацией (это сделал для проверки парсит или нет), но есть проблема - если я ещё раз на кнопку нажму появится Acces violation или вообще закроется программа. В чем может быть проблема?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
01.03.2015, 19:47
Ответы с готовыми решениями:

Ошибка при заполнении динамического массива точек
Доброго времени суток. Пишу примитивный графический редактор. На данный момент...

Ошибка 'Access violation at address 00403EF4' при вводе массива
unit Unit1; interface uses Windows, Messages, SysUtils, Variants,...

Access Violation at address. при записи в StringGrid двумерного массива
Пожалуйста, подскажите в чем здесь дело. Пытался реализовать сложение матриц....

Access violation при сравнении изображений
делаю программу для сравнения изображений перевожу в битмапы и потом смотрю по...

Access violation при вызове конструктора
Здравствуйте! У меня при вызове конструктора возникает ошибка. Access...

7
krapotkin
3437 / 3041 / 1050
Регистрация: 14.04.2014
Сообщений: 14,757
Записей в блоге: 15
01.03.2015, 20:03 2
сама ошибка заключается в том, что нигде не задается размер массива
но вообще нужно переделать саму логику работы с массивами

function ParseVK(url:string):TParse;
заменить на

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
procedure ParseVK(const URL:string; var arr:TParse);
var
     mass:TParse
     n,i:integer;
begin        
  // нужно как-то добыть количество элементов в массиве 
  N:=???;
  setLength(arr,N);
   for i:=low(arr) to high(arr) do
   begin
       arr[i].id:=i;
       arr[i].img_url:=img_url;
      {...................................................}      
   end;
end;
1
drka
1 / 1 / 1
Регистрация: 27.05.2013
Сообщений: 65
01.03.2015, 20:43  [ТС] 3
Нет, у меня по сути вместо for while стоит. Размер массива я задаю примерно так

Delphi
1
2
3
4
5
6
7
i:=0;
while regexpr.exec(response) do
begin
   setlength(mas,i+1);
   //тут парсим....
   inc(i);
end;
Добавлено через 1 минуту
И ошибка выскакивает уже при нажатии кнопки. Допустим первый раз при запуске программы я начинаю парсить страницу, все нормально, как только я нажимаю повторно на кнопку - ошибка.
0
Mawrat
12830 / 5738 / 1700
Регистрация: 19.09.2009
Сообщений: 8,807
01.03.2015, 20:51 4
Лучший ответ Сообщение было отмечено drka как решение

Решение

Добавлю. Размер массива можно увеличивать по мере добавления в него новых элементов.
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
function ParseVK(const url : String) : TParse;
const
  Capacity = 20; //Величина приращения динамического массива.
var
  i : Integer;
  Stop : Boolean;
begin
  i := 0; //Количество значимых элементов массива.
  Stop := False; //Флаг завершения цикла. True - прекратить, False - продолжать.
  while not Stop do
  begin
    {...}
    //Если требуется, увеличиваем длину массива на величину Capacity.
    if i = Length(Result) then
      SetLength(Result, i + Capacity);
    //Записываем в массив новое значение.
    Result[i].id := i;
    Result[i].img_url := img_url;
    //Отмечаем, что количество значимых элементов массива увеличилось на 1.
    Inc(i);
    {...}
  end;
  //Приводим длину массива в соответствие с количеством значимых элементов.
  if i < Length(Result) then
    SetLength(Result, i);
end;
Пример вызова:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var
   massive:TParse;
 
procedure TForm1.Button1Click(Sender: TObject);
begin
  //Здесь очищать массив не нужно. Размером массива далее управляет функция ParseVK().
  //massive := nil;
 
  massive := ParseVK(Edit1.Text);
  
  if Length(massive) > 0 then
    ShowMessage(massive[0].name_k);
  else
    ShowMessage('Массив пуст.');
end;
0
drka
1 / 1 / 1
Регистрация: 27.05.2013
Сообщений: 65
01.03.2015, 21:27  [ТС] 5
Не понял, а для чего такая "чтука"?

Delphi
1
2
const
Capacity = 20;
и это?

Delphi
1
2
if i < Length(Result) then
    SetLength(Result, i);
Добавлено через 8 минут
Mawrat, все отлично, ошибка больше не тревожит.
0
Mawrat
12830 / 5738 / 1700
Регистрация: 19.09.2009
Сообщений: 8,807
01.03.2015, 23:31 6
Лучший ответ Сообщение было отмечено drka как решение

Решение

Delphi
2
3
const
  Capacity = 20; //Величина приращения длины динамического массива.
Capacity - это величина, на которую увеличивается размер массива. Т. е., происходит следующее. Например у нас сейчас массив имеет длину 40 элементов. Мы уже записали в массив 40 элементов и теперь нам надо ещё один элемент записать - 41-й. В этом случае срабатывает код:
Delphi
13
14
15
    //Если требуется, увеличиваем длину массива на величину Capacity.
    if i = Length(Result) then
      SetLength(Result, i + Capacity);
И размер массива увеличивается на Capacity = 20. Т. е., размер массива становится равным 40 + 20 = 60 элементов. После этого в массив мы записываем 41-й элемент. Потом, когда нам понадобится записать 42-й элемент, то размер массива менять не придётся. И так будет до тех пор, когда нам понадобится записать 61-й элемент. В этот момент опять сработает код увеличения длины массива и размер массива станет равным 60 + 20 = 80 элементов. Потом мы запишем 61 элемент. Потом, если надо, запишем 62, 63 элементы и т. д.

Итак, у нас длина массива = 80 элементов. А мы, например, записали в массив 65 элементов и после этого цикл разбора HTML кода завершился. Вот эти 65 элементов - это значимые элементы. Это те элементы, для которых в цикле были присвоены значения. Это означает, что у нас в конце массива имеется 15 лишних элементов. Чтобы их убрать надо поменять длину массива с 80 на 65. Это действие выполняет следующий код:
Delphi
23
24
25
  //Приводим длину массива в соответствие с количеством значимых элементов.
  if i < Length(Result) then
    SetLength(Result, i);
Добавлено через 13 минут
Изменение длины динамического массива - это ресурсоёмкая операция. При этом происходит следующее. Для массива выделяется новая область памяти достаточного размера. Потом из прежней области памяти элементы копируются в новую область. Представим, например, что у нас массив длиной в 100 элементов и мы решили увеличить его размер на 1. При этом сначала будет выделена область памяти для массива размером 101 элемент. Потом будет запущен цикл, который из прежней области памяти побайтно скопирует содержимое и запишет его в новую область памяти - это для данного примера 100 * SizeOf(RRecord) операций копирования.
Поэтому желательно сократить количество операций по изменению размера динамического массива. Для этого, как раз, предназначен механизм с Capacity. Если Capacity=20, то это означает, что при добавлении 20 новых элементов в массив, длина массива будет изменяться не 20 раз, а только один раз. Таким образом мы существенно сокращаем вычислительную нагрузку.
0
northener
пофигист широкого профиля
3427 / 2326 / 631
Регистрация: 15.07.2013
Сообщений: 13,776
01.03.2015, 23:37 7
Таким образом мы существенно сокращаем вычислительную нагрузку.
+ уменьшаем степень неизбежно возникающей фрагментации памяти.
0
krapotkin
3437 / 3041 / 1050
Регистрация: 14.04.2014
Сообщений: 14,757
Записей в блоге: 15
05.03.2015, 10:51 8
а чтобы не думать про такие штуки вообще, используйте TObjectList ))))
0
05.03.2015, 10:51
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
05.03.2015, 10:51

Access violation при добавлении TsLabel
При добавлении TsLabel следующая ошибка... В новом проекте все нормально.. ...

Access Violation при BitMap.Create
Доброго Времени Суток! У меня в коде используется двусвязный список типа ...

Access Violation при нажатии на кнопку
Я делаю программу, она с потоком, но есть проблема. Когда нажимаю на кнопку...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
8
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru