Модераторы: Snowy, MetalFan, bems, Poseidon

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> инкрементирование динамического массива 
V
    Опции темы
VanHelsing
Дата 24.9.2011, 18:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


ХОЧУ ВСЕ ЗНАТЬ!!!
**
Награды: 1



Профиль
Группа: Участник
Сообщений: 288
Регистрация: 3.1.2008
Где: Екатеринбург

Репутация: нет
Всего: 6



Есть программа в которой используются динамические массивы. Длина массива и записываемые данные узнаются по ходу выполнения программы(в результате сравнения в цикле) и соответственно заполняю массив следующим образом:
Код

var 
  Arrti: arrary of word;
.......................................
//Здесь некое условие заполнения
  ind1 := 1;
  for i := 0 to a - 1 do
    begin
      SetLength(Arrti, ind1);
      Arrti[ind1-1] := i + 1;
    end;

В программе таких массивов несколько и периодически, при большом количестве точек возникают ошибки "Access violation". Возможно такое заполнение массива использовать неправильно. Если неправильно, то подскажите как правильно.
Заранее спасибо.


--------------------
PM MAIL   Вверх
northener
Дата 24.9.2011, 19:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1361
Регистрация: 2.9.2010

Репутация: 12
Всего: 20



Цитата(VanHelsing @  24.9.2011,  18:35 Найти цитируемый пост)
SetLength(Arrti, ind1);

Что делает эта строка в теле цикла?


--------------------
Но только лошади летают вдохновенно.
Иначе лошади разбились бы мгновенно!
PM MAIL   Вверх
VanHelsing
Дата 24.9.2011, 19:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


ХОЧУ ВСЕ ЗНАТЬ!!!
**
Награды: 1



Профиль
Группа: Участник
Сообщений: 288
Регистрация: 3.1.2008
Где: Екатеринбург

Репутация: нет
Всего: 6



Цитата

Что делает эта строка в теле цикла?

Допустим сначала я установил длину массив 1, а затем инкрементировал переменную Ind1, то есть увеличиваю длину массива на единицу.


--------------------
PM MAIL   Вверх
northener
Дата 24.9.2011, 20:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1361
Регистрация: 2.9.2010

Репутация: 12
Всего: 20



Зачем устанавливать массиву одну и ту же длину Ind1 a раз? 


--------------------
Но только лошади летают вдохновенно.
Иначе лошади разбились бы мгновенно!
PM MAIL   Вверх
VanHelsing
Дата 24.9.2011, 20:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


ХОЧУ ВСЕ ЗНАТЬ!!!
**
Награды: 1



Профиль
Группа: Участник
Сообщений: 288
Регистрация: 3.1.2008
Где: Екатеринбург

Репутация: нет
Всего: 6



Извиняюсь одну строчку не скопировал.
Код

var 
  Arrti: arrary of word;
.......................................
//Здесь некое условие заполнения
  ind1 := 1;
  for i := 0 to a - 1 do
    begin
      SetLength(Arrti, ind1);
      Arrti[ind1-1] := i + 1;
      Inc(ind1);
    end;



--------------------
PM MAIL   Вверх
northener
Дата 24.9.2011, 21:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1361
Регистрация: 2.9.2010

Репутация: 12
Всего: 20



Цитата(VanHelsing @  24.9.2011,  20:43 Найти цитируемый пост)
var 
  Arrti: arrary of word;
.......................................
//Здесь некое условие заполнения
  ind1 := 1;
  for i := 0 to a - 1 do
    begin
      SetLength(Arrti, ind1);
      Arrti[ind1-1] := i + 1;
      Inc(ind1);
    end;

В этом коде неправильно то, что массиву многократно меняют длину. Это приводит к многократному перевыделению памяти. Что в конце концов приводит к фрагментации памяти, а иногда и к её нехватке. Но причин для AV именно в этом коде нет.


--------------------
Но только лошади летают вдохновенно.
Иначе лошади разбились бы мгновенно!
PM MAIL   Вверх
VanHelsing
Дата 24.9.2011, 21:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


ХОЧУ ВСЕ ЗНАТЬ!!!
**
Награды: 1



Профиль
Группа: Участник
Сообщений: 288
Регистрация: 3.1.2008
Где: Екатеринбург

Репутация: нет
Всего: 6



В программе  4 таких заполнений массивов,массивы могут быть очень большой длины.
Существуют ли другие способы реализации данной проблемы, ведь как я понимаю перевыделение памяти неправильно??


--------------------
PM MAIL   Вверх
Keeper89
Дата 24.9.2011, 21:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2580
Регистрация: 26.2.2009

Репутация: 9
Всего: 58



А что за объект?


--------------------
PM MAIL WWW   Вверх
northener
Дата 24.9.2011, 23:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1361
Регистрация: 2.9.2010

Репутация: 12
Всего: 20



Цитата(VanHelsing @  24.9.2011,  21:32 Найти цитируемый пост)
ведь как я понимаю перевыделение памяти неправильно?

Неправильно понимаете. Во многих реальных задачах без перевыделения памяти под динамический массив никак не обойтись не создавая иные проблемы. Но вот многократное изменение размера "большого" массива при добавлении/удалении одного элемента размером 2 байта на его размер - это перебор!
Нужно этот процесс как-то оптимизировать. А что-то советовать можно только зная вашу задачу. О чём Keeper89 и спросил.
От себя спрошу. Что есть для вас "большой массив"?

P.S. Поискал наспех в Блоге CodeMonkee, ничего не нашёл по теме. Хотя вроде бы что-то, когда-то именно там читал по этому вопросу. Или не там???

Это сообщение отредактировал(а) northener - 24.9.2011, 23:22


--------------------
Но только лошади летают вдохновенно.
Иначе лошади разбились бы мгновенно!
PM MAIL   Вверх
VanHelsing
Дата 25.9.2011, 06:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


ХОЧУ ВСЕ ЗНАТЬ!!!
**
Награды: 1



Профиль
Группа: Участник
Сообщений: 288
Регистрация: 3.1.2008
Где: Екатеринбург

Репутация: нет
Всего: 6



Задача состоит в следующем.
Реализую свой алгоритм, он конечно неправильный и медленный, но других вариантов пока нет. Беру массив замыкаемых точек делю по принципу - четный, нечетный. Произвожу замыкание. Если нет ошибок, но записываю все возможные комбинации замкнутых точек. Например:
Код

+ - + - + -
1 2 3 4 5 6
 
Если нет ошибок, то формируется следующий массив
Код

1,2 1,4 1,6 3,2 2,4 3,6 5,2 5,4 5,6

Если ошибки есть, то массив записывается точно также.
Потом происходит перемешивание массива и вся процедура повторяется. Далее я сравниваю два этих массива и выявляю в массиве с ошибка, только те точки, которые не содержатся в массиве без ошибок.
Каждый из приведенных массивов у меня динамический и я их увеличиваю как приведено выше.
Цитата

От себя спрошу. Что есть для вас "большой массив"?

Например при размере в 100 точек, длина одного массива - 5000, а второго - 1250.


--------------------
PM MAIL   Вверх
THandle
Дата 25.9.2011, 09:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Хранитель Клуба
Group Icon
Награды: 1



Профиль
Группа: Админ
Сообщений: 3639
Регистрация: 31.7.2007
Где: Moscow, Dubai

Репутация: 50
Всего: 372



VanHelsing, а почему бы сразу не установить длину массива равную a? судя по коду у тебя длина статическая и вообще не меняется. Прям перед циклом сделай один раз SetLength(Arrti, a) и все.
Получится что то типа:

Код

  SetLength(Arrti, a);    
  for ind1 := 1 to a do
    Arrti[ind1 - 1] := ind1;


Если у тебя память все таки надо перераспределять, то посмотри как это сделано в каких-нибудь списках, например в TStringList(см свойство Capacity и связанные с ним методы + методы добавления).

PM   Вверх
VanHelsing
Дата 25.9.2011, 10:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


ХОЧУ ВСЕ ЗНАТЬ!!!
**
Награды: 1



Профиль
Группа: Участник
Сообщений: 288
Регистрация: 3.1.2008
Где: Екатеринбург

Репутация: нет
Всего: 6



Цитата

VanHelsing, а почему бы сразу не установить длину массива равную a? судя по коду у тебя длина статическая и вообще не меняется. Прям перед циклом сделай один раз SetLength(Arrti, a) и все.

Не получится, потому что заранее неизвестно сколько раз выполнится условие.

P.S. перед использование динамические массивы необходимо обнулять?

Это сообщение отредактировал(а) VanHelsing - 25.9.2011, 11:02


--------------------
PM MAIL   Вверх
THandle
Дата 25.9.2011, 14:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Хранитель Клуба
Group Icon
Награды: 1



Профиль
Группа: Админ
Сообщений: 3639
Регистрация: 31.7.2007
Где: Moscow, Dubai

Репутация: 50
Всего: 372



Цитата(VanHelsing @  25.9.2011,  11:31 Найти цитируемый пост)

Не получится, потому что заранее неизвестно сколько раз выполнится условие.


Судя по коду, который ты дал не понятно. Там в любом случае длина массива становится равной a(так как ind1 изначально равен 1).

Сделай как это делается в списках(или вообще через сами списки).

Вот код добавления элемента в TStringList:

Код

procedure TStringList.InsertItem(Index: Integer; const S: string; AObject: TObject);
begin
  Changing;
  if FCount = FCapacity then Grow;
  if Index < FCount then
    System.Move(FList^[Index], FList^[Index + 1],
      (FCount - Index) * SizeOf(TStringItem));
  with FList^[Index] do
  begin
    Pointer(FString) := nil;
    FObject := AObject;
    FString := S;
  end;
  Inc(FCount);
  Changed;
end;


Если число элементов(FCount) = Количеству выделенной памяти, то перевыделяем.
Код


procedure TStringList.Grow;
var
  Delta: Integer;
begin
  if FCapacity > 64 then Delta := FCapacity div 4 else
    if FCapacity > 8 then Delta := 16 else
      Delta := 4;
  SetCapacity(FCapacity + Delta);
end;


Аналогичено можно сделать и у ебя. Сделать выделение памяти на, допустим 100 элементов, и добавлять. Как память кончится, выделить еще на какое-то Delta(10-20...). В конце можно ненужное подчистить.
PM   Вверх
VanHelsing
Дата 25.9.2011, 14:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


ХОЧУ ВСЕ ЗНАТЬ!!!
**
Награды: 1



Профиль
Группа: Участник
Сообщений: 288
Регистрация: 3.1.2008
Где: Екатеринбург

Репутация: нет
Всего: 6



Цитата

Судя по коду, который ты дал не понятно. Там в любом случае длина массива становится равной a(так как ind1 изначально равен 1).

Представляю фрагмент кода
Код

procedure TForm1.btnGenerationArClick(Sender: TObject);
var
  Arrti_x: array of Word;
  sch, i, count_point, j: Word;
  NumPoint: Word;
begin
   {По циклу проиходят перестановки }
  count_point := a;
  SetLength(Arrti_x, a);
  while (count_point>=1) do
   begin
     SCH := 0;
     For I := 0 to a - 1 do
       begin
        if ((I+1) mod 2) <> 0 then
         begin
           ArRTI_X[sch] := ArRTI[I];
           INC(SCH);
         end;
       end;
     For I := 0 to a - 1 do
       begin
        if ((I+1) mod 2) = 0 then
         begin
           ArRTI_X[sch] := ArRTI[I];
           INC(SCH);
         end;
       end;
     For I := 0 to a - 1 do ArRTI[I] := ArRTI_X[I];
     //моделируем ошибки
     NumPoint := 0;
     case Application.MessageBox('Если в данной проверке ошибка?',
       'Наличие ошибки', MB_YESNO + MB_ICONQUESTION) of
       IDYES: //Ошибка произошла
         begin
           NumPoint := ((a div 2)*(a div 2))*2;
           SetLength(ArErr, IndErr+NumPoint);
           i := 0;
           while (i<(a-1)) do
             begin
               for j := 0 to a - 1 do
                 begin
                   if (j mod 2)<>0 then
                     begin
                       IndErr := IndErr + 2;
                       ArErr[IndErr-2] := Arrti[i];
                       ArErr[IndErr-1] := Arrti[j];
                       mmoArError.Lines.Add(IntToStr(Arrti[i])+' - '+IntToStr(Arrti[j]));
                     end;
                 end;
               i := i + 2;
             end;
         end;
       IDNO:
         begin
           NumPoint := ((a div 2)*(a div 2))*2;
           SetLength(ArNotErr, IndNotErr+NumPoint);
           i := 0;
           while (i<(a-1)) do
             begin
               for j := 0 to a - 1 do
                 begin
                   if (j mod 2)<>0 then
                     begin
                       IndNotErr := IndNotErr + 2;
                       ArNotErr[IndNotErr-2] := Arrti[i];
                       ArNotErr[IndNotErr-1] := Arrti[j];
                       mmoArError.Lines.Add(IntToStr(Arrti[i])+' - '+IntToStr(Arrti[j]));
                     end;
                 end;
               i := i + 2;
             end;

         end;
     end;
    count_point := count_point div 2;
  end;
end;

Получается команда
Код

    System.Move(FList^[Index], FList^[Index + 1],
      (FCount - Index) * SizeOf(TStringItem));

производит выделения памяти?


--------------------
PM MAIL   Вверх
THandle
Дата 25.9.2011, 14:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Хранитель Клуба
Group Icon
Награды: 1



Профиль
Группа: Админ
Сообщений: 3639
Регистрация: 31.7.2007
Где: Moscow, Dubai

Репутация: 50
Всего: 372



Цитата(VanHelsing @  25.9.2011,  15:41 Найти цитируемый пост)
производит выделения памяти? 


Нет... Посмотри исходники TSTringList'а... Рассчет перераспределения происходит в Grow(см. мой пост выше).
Там вызывается SetCapacity:

Код

procedure TStringList.SetCapacity(NewCapacity: Integer);
begin
  if (NewCapacity < FCount) or (NewCapacity > MaxListSize) then
    Error(@SListCapacityError, NewCapacity);
  if NewCapacity <> FCapacity then
  begin
    ReallocMem(FList, NewCapacity * SizeOf(TStringItem));
    FCapacity := NewCapacity;
  end;
end;


вот там память и перераспределяется. Тебе нужно просто заимствовать эту идею, либо уже готовое использовать.
PM   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Для новичков"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.1086 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.