Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 06.08.2015, 10:57   #1
Masam
Пользователь
 
Регистрация: 19.11.2009
Сообщений: 19
По умолчанию Ошибка Access Violation при переделывании из TStrings в динамический массив

Добрый день. Помогите пожалуйста отловить ошибку доступа к памяти. Есть программа клиент-серверная, серверная часть собирает данные кто сидит в расшареных папках на серваке, собирает их динамический массив, далее что бы передать эти данные на компьютер клиента переделывает массив в TStrings и через инди компонет (TCPServer) отправляет клиентской части. В клиентской части массив собирается заново из TStrings и дальше вывод на СтрингГрид.
При ручном запросе данных с сервера все работает хорошо, но стоит сделать что бы данные автоматически обновлялись скажем раз в 1 сек. и когда происходит какое либо подключение к шарам, то тут же выскакивает ошибка.

П.С.: Всего передается два массива двумерных у них строки это столбцы, а столбцы это строки (так проще в стринггрид писать да и дело привычки). В TStrings массив переделывается следующим путем: строка массива объединяется по всем полям и запихивается в строку TStrings, а что бы можно было отделить одно поле от другого ставится символ "#".

Надеюсь более менее описал ситуацию понятной. =)

Код серверной части пока не привожу, думаю дело не в ней.

Код клиентской программы:

Код:
type
  DynMas=array of array of string;

var
  Form1: TForm1;
  MatUsers,MatFileUse,MatAll:DynMas;
  globI,globJ:integer;
  TempN:integer;

//Функции
//Функция переэтования многострочки в матрицу
//-------------------------------------------------------------------------
Function fStringsMatrix(StrTmp:TStrings):DynMas;
var
 i,j:integer;
 StrN,StrI:integer;
 TmpStrI:integer;
 Str:string;
begin
globI:=StrTmp.Count;
globJ:=0;
Str:=StrTmp[0];
StrN:=Length(Str);

 for i:=1 to StrN do
  if copy(Str,i,1)='#' then globJ:=globJ+1;

SetLength(Result,globJ,globI);
 for i:=0 to globI-1 do
  begin
  Str:=StrTmp[i];
  StrN:=length(Str);
  j:=0;
  TmpStrI:=0;
   for StrI:=1 to StrN do
    if copy(Str,StrI,1)='#' then
     begin
     Result[j,i]:=copy(Str,TmpStrI+1,StrI-TmpStrI-1);
     j:=j+1;
     TmpStrI:=StrI;
     end;
  end;
end;

//Функция определения количества строк в дин. массиве
//-------------------------------------------------------------------------
Function fRowCountDynMas(Matrix:DynMas):integer;
begin
Result:=Length(Matrix);
end;

//Функция определения количества столбцов в дин. массиве
//-------------------------------------------------------------------------
Function fColCountDynMas(Matrix:DynMas):integer;
begin
Result:=1;
 if Length(Matrix)>0 then Result:=Length(Matrix[0]);
end;

//Функция поиска определеной строки в колонке NamePC массива
//-------------------------------------------------------------------------
Function fFindMatrix(StrFind:string;Matrix:DynMas):integer;
var
 i,n:integer;
begin
Result:=-1;
n:=fColCountDynMas(Matrix);
 for i:=0 to n-1 do
  if Matrix[1,i]=StrFind then Result:=i
end;
//-------------------------------------------------------------------------
О_о

Последний раз редактировалось Аватар; 06.08.2015 в 11:02.
Masam вне форума Ответить с цитированием
Старый 06.08.2015, 10:58   #2
Masam
Пользователь
 
Регистрация: 19.11.2009
Сообщений: 19
По умолчанию

Код:
//Код кнопки. (не вместился.)
//-------------------------------------------------------------------------
Procedure TForm1.BtnGetSrvClick(Sender: TObject);
var
 StrMUsers,StrMFileUse:TStrings;
 i,j,iFind,iDop,k:integer;
 maskCons,maskDocPU,maskBing, maskENS:string;
 AddMatrix:boolean;
begin
 try
 maskCons:='ConsultantPlus';
 maskDocPU:='DocPU5';
 maskBing:='Bing';
 maskENS:='ens_omts';

 Client.Disconnect;
 Client.Connect;

 StrMUsers:=TStringList.Create();
 StrMFileUse:=TStringList.Create();

 Client.ReadStrings(StrMFileUse,TempN);
 Client.ReadStrings(StrMUsers,TempN);

 MatFileUse:=fStringsMatrix(StrMFileUse);
 MatUsers:=fStringsMatrix(StrMUsers);

 globI:=fColCountDynMas(MatFileUse);
 globJ:=6;
 SetLength(MatAll,globJ,globI);

 //Нужно еще добавить разделение на две таблицы одну по маскам, а вторая остальное
 //Или не так??? нужно подумать...
 //Объединяем две таблицы
  for i:=0 to globI-1 do
   begin
   iFind:=fFindMatrix(MatFileUse[2,i],MatUsers);
    if iFind>=0 then
     begin
     MatAll[0,i]:=MatUsers[0,iFind];
     MatAll[1,i]:=MatFileUse[2,i];
     MatAll[2,i]:=MatFileUse[1,i];
     MatAll[3,i]:=MatUsers[2,iFind];
     MatAll[4,i]:=MatUsers[3,iFind];
     MatAll[5,i]:=MatUsers[4,iFind];
     //сокращение адреса расшары до маски.
     k:=length(maskCons);
      if copy(MatAll[2,i],4,k)=maskCons then MatAll[2,i]:=maskCons;
     k:=length(maskBing);
      if copy(MatAll[2,i],4,k)=maskBing then MatAll[2,i]:=maskBing;
     k:=length(maskDocPU);
      if copy(MatAll[2,i],4,k)=maskDocPU then MatAll[2,i]:=maskDocPU;
     k:=length(maskENS);
      if copy(MatAll[2,i],4,k)=maskENS then MatAll[2,i]:=maskENS;
    end;
   end;
 //Тут бы желательно деактивировать два масиива: MatUsers, MatFileUse.
 Finalize(MatFileUse);
 Finalize(MatUsers);

 //пошла вода в хату, цикл на цикле и циклом погоняет...
 //множественный цикл для сравнения каждого с каждым и добавлением
 //в новый отсортированный массив.
 //изначально сравнивыемый элемент считается не повторимым, но если при
 //сравнении находится подобный элемент, то внутрений цикл прерывается и
 //и выбирается новый сравнивыемый элемент.
 iDop:=-1;
  for i:=0 to globI-1 do
   begin
   AddMatrix:=true;
    for j:=i+1 to globI-1 do
     begin
      if (MatAll[0,i]=MatAll[0,j])and
         (MatAll[2,i]=MatAll[2,j]) then
       begin
       AddMatrix:=false;
       Break;
       end;
     end;
    if AddMatrix=true then
     begin
     iDop:=iDop+1;
      for k:=0 to globJ-1 do
       MatAll[k,iDop]:=MatAll[k,i];
     end;
   end;

 //для инициализации сорт. массива нужно увеличить кол-во строк на 1.
 globI:=iDop+1;
 SetLength(MatAll,globJ,globI);
  for i:=0 to globI-1 do
  for j:=0 to globJ-1 do
   begin
   SGBT.Cells[0,i+1]:=inttostr(i);
   SGBT.Cells[j+1,i+1]:=MatAll[j,i];
   end;
 SGBT.RowCount:=globI+1;

 //Процедура выравнивания ширины колонок в SG
 pSGAlignWidth(SGBT);

 Form1.AutoSize:=false;
 Form1.AutoSize:=true;

 finally
 FreeAndNil(StrMFileUse);
 FreeAndNil(StrMUsers);
 Finalize(MatFileUse);
 Finalize(MatUsers);
 Finalize(MatAll);
 Client.Disconnect;
 end;
end;
О_о

Последний раз редактировалось Аватар; 06.08.2015 в 11:02.
Masam вне форума Ответить с цитированием
Старый 06.08.2015, 11:01   #3
Masam
Пользователь
 
Регистрация: 19.11.2009
Сообщений: 19
По умолчанию

отладчик при ошибке выводит на эту строчку в функции fStringsMatrix

Result[j,i]:=copy(Str,TmpStrI+1,StrI-TmpStrI-1);
О_о
Masam вне форума Ответить с цитированием
Старый 06.08.2015, 11:11   #4
min@y™
Цифровой кот
Старожил
 
Аватар для min@y™
 
Регистрация: 29.08.2014
Сообщений: 7,629
По умолчанию

TStringList ---> массив ---> TStringList ?
нафига такой онанизм? без преобразования никак? зачем оно ваще?
Расскажу я вам, дружочки, как выращивать грибочки: нужно в поле утром рано сдвинуть два куска урана...
min@y™ вне форума Ответить с цитированием
Старый 06.08.2015, 11:12   #5
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

Дык бряк поставь в теле функции и смотри при каких значениях индексов исключение произошло
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Старый 06.08.2015, 11:17   #6
Masam
Пользователь
 
Регистрация: 19.11.2009
Сообщений: 19
По умолчанию

Для min@y™

Нет. Масcив -> TStringList -> передача по сети через инди компоненты -> TStringList -> Масcив. Нужно для того что бы с серверной части передать на клиентскую часть (две разные программы), не смог реализовать через Stream, сделал проще у компонента IdTCPServer, есть метод передачи данных через WriteStrings (AThread.Connection.WriteStrings)

Для Аватар
Ошибка появляется только в определенный момент времени, не могу отловить так.
(Кстати спасибо за исправление кода в человеческий вид, не нашел как сделать его таким).
О_о

Последний раз редактировалось Masam; 06.08.2015 в 11:21.
Masam вне форума Ответить с цитированием
Старый 06.08.2015, 11:23   #7
JUDAS
фонатик DELPHI
Форумчанин
 
Аватар для JUDAS
 
Регистрация: 14.01.2008
Сообщений: 714
По умолчанию

Автор, прежде чем отвечать на твой вопрос, расскажи мне, зачем в твоём приложении динамические массивы вообще нужны? их предназначение
95% сбоев и ошибок приложений, находится в полу метрах от монитора
JUDAS вне форума Ответить с цитированием
Старый 06.08.2015, 11:29   #8
Masam
Пользователь
 
Регистрация: 19.11.2009
Сообщений: 19
По умолчанию

Для JUDAS
Дин. Массивы нужны, для того что не известно сколько человек подключено и сколько у них открыто файлов в расшареных папках на серваке, и что бы не выйти за границы с фиксированного массива, проще все это отлавливать в коде программы.

Если более конкретно, то можно объяснить так: в Windows XP, в управлении компьютером (запускается так ПКМ на "мой компьютер" -> Управление), открыть древо Служебные программы -> Общие папки, там есть два пункта "сеансы" и "открытые файлы", если на них нажать, то увидим две таблицы они и передаются в каждый свой массив, который переделывается в TStringList и далее как писал выше.
О_о

Последний раз редактировалось Masam; 06.08.2015 в 11:38.
Masam вне форума Ответить с цитированием
Старый 06.08.2015, 11:35   #9
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

В какой-то из строк стриглиста больше символов # чем в первой строке. Либо в первой строке они вообще отсутствуют
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Старый 06.08.2015, 11:47   #10
JUDAS
фонатик DELPHI
Форумчанин
 
Аватар для JUDAS
 
Регистрация: 14.01.2008
Сообщений: 714
По умолчанию

Хорошо, я тебе отвечу где в тебя ошибка, но советую прислушаться к словам Миная и переписать код.
----------
максимальная длина массива у тебя формируется по первой строке
вопрос, а если вторая строка длинее первой а третья короче второй, что произойдёт?
aa#bb#cc
aa#bb#cc#dd#ee#ff
aa#bb

... а произойдёт попытка записи четвёртого элемента второй строки в массив с трёх ячеек

вот тут, ищется самая длинная строка и по ней формируется размер массива
Код:
 for j:=0 to globI-1 do
 begin
   Str  := StrTmp.Strings[j];
   for i:=1 to Length(Str) do
    if copy(Str,i,1)='#' then d:=d+1;
   if d>globJ then globJ:=d;
 end;
п.с. а текстовый парсер у тебя автор, никудышний. Я так и не понял что там и как разбирается и передаётся.
95% сбоев и ошибок приложений, находится в полу метрах от монитора
JUDAS вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Ошибка при создании матрицы (access violation) Svejk Помощь студентам 3 24.08.2013 14:30
Ошибка при вызове функции Access violation Hottabych Win Api 1 22.01.2011 20:35
TList. Ошибка Access Violation при создании. thexqn Помощь студентам 3 28.11.2010 21:01