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

Вниз

Глюк в динамическом массиве Delphi   Найти похожие ветки 

 
AlexA ©   (2012-12-14 15:05) [0]

Есть структура
PR = record // Структура массива родителя
N: Integer; // Номер
I_: Integer; // Вход
OU_: Integer; // Выход
S_: Integer; // Старт
F_: Integer; // Финиш
C_: Integer; // Счетчик ссылок
end;

Массив
ContPar = record
Tpr: array of PR; // Массив родителей

Код
RDN_B:=2; integer
RDK_A:=1; integer
G1.Tpr[RDK_A].OU_:=RDN_B;
В после последней строчки в массиве G1.Tpr в строчке 0 появляется данные из строчки 1, а значение RDN_B записывается в строчку 1 как и должно быть, при записи в строчку 2 и далее такого нет

Тут скриншот таблицы http://89166974791.webasyst.net/DD/2...B_KEY=QUMxNjQ4
Видно в 0 строке цифры, а записывали в 1 строку, причем только в одну ячейку 1,О = 2. А в строке 0 появились 0,F=5 0,C=1
Как с этим бороться то?


 
Jeer ©   (2012-12-14 15:24) [1]

Каша..
И что такое G1 ?


 
KilkennyCat ©   (2012-12-14 15:26) [2]

инициализация массива делается? иначе мусор будет


 
AlexA ©   (2012-12-14 16:07) [3]

G1: ContPar;
инициализация делается, размер массива тоже установлен и его хватает
Пишем в строку 1, а значения появляются в строке 0 и в строке 1


 
O'ShinW ©   (2012-12-14 16:08) [4]

и ссылка битая


 
KilkennyCat ©   (2012-12-14 16:10) [5]

ну код-то приведи. здесь нет телепатов.


 
O'ShinW ©   (2012-12-14 16:11) [6]


> инициализация делается,

как?


 
AlexA ©   (2012-12-14 16:14) [7]

SetLength(G1.Tpr, 0);
SetLength(G1.Tpr, G1.IM_C);
G1.IM_C - рассчитывается раньше и ее размер всегда больше чем будет записей


 
KilkennyCat ©   (2012-12-14 16:18) [8]

ты весь код приводи, тебя что, пытать надо?


 
O'ShinW ©   (2012-12-14 16:20) [9]


> SetLength(G1.Tpr, 0);
> SetLength(G1.Tpr, G1.IM_C);

// a обнулить?
// оф чего они там уж..
ZeroMemory(G1.Tpr, G1.IM_C * SizeOf(PR) );
// так вроде..


 
AlexA ©   (2012-12-14 16:20) [10]

Код лежит в архиве по ссылке http://89166974791.webasyst.net/DD/2.0/folder_link.php?sl=94e0dae428c1ce3a79eecd049fee567d&DB_KEY=QUMxNjQ4

При запуске надо выбрать файл Тест_Стандартная петля (в архиве лежит)
Затем последовательно Заполним точки,Анализ, Проявить

Слева две таблички, там наблюдаем глюк

В коде изменение переменной строка 321

Прога берет файл картинки, преобразует в битовую карту и ищет связанные пикселы (аналог bwlable из MATLAB) если выбрать галку в таблицу, реномер, проявить, то в таблице появятся все связанные объекты
под своими номерами. Вот и не работает она при некоторых изображениях на входе, с тестовым примеро точно глючит, если крин шот кода который я оправил пропустить то все ок)

Да делфи Embarcadero® Delphi® XE2 Version 16.0.4504.48759


 
KilkennyCat ©   (2012-12-14 16:24) [11]

код надо приводить нормально, как есть.
твой код:
SetLength(G1.Tcp, 0); // Очистим массив цепочек
   SetLength(G1.Tcp, G1.IM_C);

это неверно. смотри [9]


 
KilkennyCat ©   (2012-12-14 16:27) [12]

и не спеши называть глюком свои ошибки ;)


 
O'ShinW ©   (2012-12-14 16:29) [13]

еще,
если появляется трудноуловимый глюк с индексом доступа
тогда надо сделать доступ по свойству.

А в геттере/сеттере можно уже тупо написать
if (вообще быть не может) then
 raise Exception.Create("вообще быть не может, а есть");
далее по стеку вызовов смотрим откуда ноги растуту

"Багель отладчик" - в гугле искать


 
AlexA ©   (2012-12-14 17:08) [14]

Глюк выскакивает на некоторых изображениях. Тем более когда SetLength установлен размер достаточный для работы. даже если в массиве мусор, то как при одних и тех де условиях запись в строку 1 вызывает появление значений в строке 0 из других строк, а запись в строку 2 работает нормально? На что повлияет способ установки длинны массива?
Тогда уже при записи в строку 2 должна быть ошибка или же до выполнения записи уже должны быть неправильные значения.


 
KilkennyCat ©   (2012-12-14 17:44) [15]


> или же до выполнения записи уже должны быть неправильные
> значения.

или правильные. иногда мусор бывает "верным". что есть массив? некий список адресов на ячейки памяти. изменяя размер массива изменяешь лишь список адресов, но не содержимое. и вполне возможна ситуация, когда захватываешь область памяти, которая была захвачена до этого, и за промежуток между
SetLength(G1.Tcp, 0);
SetLength(G1.Tcp, G1.IM_C);
ее ничто не успело изменит, или изменило частично.


 
AlexA ©   (2012-12-14 20:49) [16]

Ошибка стабильно повторяется и числа те же, пробовал перезагружать комп


 
NoUser   (2012-12-15 18:38) [17]

> Ошибка стабильно повторяется и числа те же, пробовал перезагружать комп
??

file - point - analiz -> Svazat(PTI.A, C1 = (1635360) ); ->
->
procedure TF1.Svazat(A: Integer; B: Integer);
begin
ACp := G1.Tcp[A];
BCp := G1.Tcp[B];  //  Length(G1.Tcp) = 481;

->-> ?? Глюк в динамическом массиве Delphi ??


 
begin...end ©   (2012-12-15 19:22) [18]

> KilkennyCat ©   (14.12.12 16:24) [11]

> смотри [9]

Это вряд ли.


 
begin...end ©   (2012-12-15 19:27) [19]

Хотя в отношении именно XE2 не уверен, сорри.


 
KilkennyCat ©   (2012-12-15 19:35) [20]


> begin...end ©   (15.12.12 19:22) [18]

не уверен, что так обнуляют, или в необходимости?


 
begin...end ©   (2012-12-15 19:42) [21]

> KilkennyCat ©   (15.12.12 19:35) [20]

В необходимости. В D7 при расширении такого массива новые элементы обнулятся сами. Как с этим в новых версиях - не в курсе.


 
KilkennyCat ©   (2012-12-15 20:15) [22]

у меня был мусор в D7.
в XE2 используется DynArraySetLength , которая в свою очередь вызывает:
...
if newLength <= 0 then
 begin
   if newLength < 0 then
     Error(reRangeError);
   DynArrayClear(a, typeInfo);
   exit;
 end;
...


 
begin...end ©   (2012-12-15 20:54) [23]

> KilkennyCat ©   (15.12.12 20:15) [22]
> у меня был мусор в D7.

Ничего не путаете? В D7-версии DynArraySetLength новый участок памяти, выделенный под динамический массив, fillchar"ится нулями.


 
KilkennyCat ©   (2012-12-15 21:19) [24]


> begin...end ©   (15.12.12 20:54) [23]

не путаю. DynArraySetLength я в 7-ой вообще не помню (точнее, я не знал тогда, есть сие вообще или нет).  SetLength делает инициализацию лишь в определенных случаях. Автор использует последнюю.


 
begin...end ©   (2012-12-15 21:25) [25]

> KilkennyCat ©   (15.12.12 21:19) [24]

procedure DynArraySetLength(var a: Pointer; typeInfo: Pointer; dimCnt: Longint; lengthVec: PLongint);
var
 i: Integer;
 newLength, oldLength, minLength: Longint;
 elSize: Longint;
 neededSize: Longint;
 p, pp: Pointer;
begin
 p := a;

 // Fetch the new length of the array in this dimension, and the old length
 newLength := PLongint(lengthVec)^;
 if newLength <= 0 then
 begin
   if newLength < 0 then
     Error(reRangeError);
   DynArrayClear(a, typeInfo);
   exit;
 end;

 oldLength := 0;
 if p <> nil then
 begin
   Dec(PLongint(p));
   oldLength := PLongint(p)^;
   Dec(PLongint(p));
 end;

 // Calculate the needed size of the heap object
 Inc(PChar(typeInfo), Length(PDynArrayTypeInfo(typeInfo).name));
 elSize := PDynArrayTypeInfo(typeInfo).elSize;
 if PDynArrayTypeInfo(typeInfo).elType <> nil then
   typeInfo := PDynArrayTypeInfo(typeInfo).elType^
 else
   typeInfo := nil;
 neededSize := newLength*elSize;
 if neededSize div newLength <> elSize then
   Error(reRangeError);
 Inc(neededSize, Sizeof(Longint)*2);

 // If the heap object isn"t shared (ref count = 1), just resize it. Otherwise, we make a copy
 if (p = nil) or (PLongint(p)^ = 1) then
 begin
   pp := p;
   if (newLength < oldLength) and (typeInfo <> nil) then
     FinalizeArray(PChar(p) + Sizeof(Longint)*2 + newLength*elSize, typeInfo, oldLength - newLength);
   ReallocMem(pp, neededSize);
   p := pp;
 end
 else
 begin
   Dec(PLongint(p)^);
   GetMem(p, neededSize);
   minLength := oldLength;
   if minLength > newLength then
     minLength := newLength;
   if typeInfo <> nil then
   begin
     FillChar((PChar(p) + Sizeof(Longint)*2)^, minLength*elSize, 0);
     CopyArray(PChar(p) + Sizeof(Longint)*2, a, typeInfo, minLength)
   end
   else
     Move(PChar(a)^, (PChar(p) + Sizeof(Longint)*2)^, minLength*elSize);
 end;

 // The heap object will now have a ref count of 1 and the new length
 PLongint(p)^ := 1;
 Inc(PLongint(p));
 PLongint(p)^ := newLength;
 Inc(PLongint(p));

 // Set the new memory to all zero bits
 FillChar((PChar(p) + elSize * oldLength)^, elSize * (newLength - oldLength), 0);


 // Take care of the inner dimensions, if any
 if dimCnt > 1 then
 begin
   Inc(lengthVec);
   Dec(dimCnt);
   for i := 0 to newLength-1 do
     DynArraySetLength(PPointerArray(p)[i], typeInfo, dimCnt, lengthVec);
 end;
 a := p;
end


 
KilkennyCat ©   (2012-12-15 21:54) [26]

тож самое...
но мусор был. хоть убей :)


 
KilkennyCat ©   (2012-12-15 22:09) [27]

И вот еще помнится, что как-то на встрече в москве спорили об этом, и вроде тогда кто-то высказал, что в делфи возможен мусор, в си (того же борланда) гарантированно нулится.


 
Игорь Шевченко ©   (2012-12-15 23:45) [28]


>  и вроде тогда кто-то высказал, что в делфи возможен мусор,
>  в си (того же борланда) гарантированно нулится.


Это спьяну


 
KilkennyCat ©   (2012-12-15 23:54) [29]

это вряд ли, было только пиво. скорее всего, я что-то не так запомнил.


 
O'ShinW ©   (2012-12-16 10:48) [30]

тогда вариант  [13]
ContPar не record, а class.


 
AlexA ©   (2012-12-16 16:12) [31]

Вот новые подробности!
Назначаю размер массиву
заполняю его нулями в цикле
Запускаю процедуру
ставлю условие на проверку значения из массива вне заданного диапазона (оно не может быть более чем известная переменная)
В итоге вылазит несколько ячеек с мусором
И это стабильно.
Сделал вместо массива чтение запись в StringGrid и глюк пропал!!!!!.
Вывод: динаимческий двумерный массив после установки его размера и обнуления может содержать мусор, и этот мусор появляется при попытке чтения/записи
И еще хохма, вынес фрагмент на котором проявлялся глюк из процедуры
в вызывающую процедуру и значение записалось правильно!!!!))

Даже было замечено что вставка по ходу программы фрагмента для вывода информации типа:
Memo1.Lines.Add(inttostr(BI.N)+"|"+inttostr(zveno));
приводит к тому что другой код работает иначе....
Ничего не могу понять, что это?


 
Styx   (2012-12-16 17:00) [32]


> Ничего не могу понять, что это?

А это то, что у Вас какой-то код совсем в другом месте лезет не туда, куда ему надо...


 
Игорь Шевченко ©   (2012-12-16 18:44) [33]

memproof, fastmm


 
Sapersky   (2012-12-16 18:47) [34]

Range Check для начала (автору пояснение - в настройках компилятора).

Правда, на старых Delphi ([D2] в заголовке - это серьёзно?) оно не всегда работает, если record размером больше 8 байт, то вроде бы нет.


 
AlexA ©   (2012-12-16 20:33) [35]

Код то лезет, но как такое может быть. В область памяти занятую динамическим массивом лезет код..?))


 
Sapersky   (2012-12-16 21:11) [36]

"Лезет" в смысле пишет не в ту область.
Банальный выход индекса за границы может дать невероятно экзотические глюки. Будешь думать на всё что угодно, вплоть до аппаратных проблем. Сам как-то несколько дней провозился.
В общем, включай Range Check.


 
AlexA ©   (2012-12-16 21:34) [37]

Вот мил человек натолкнул на мысль!!!
Проверил, действительно нашелся таки момент. Исправил тестим, пока все гладко



Страницы: 1 вся ветка

Текущий архив: 2013.08.25;
Скачать: CL | DM;

Наверх




Память: 0.57 MB
Время: 0.012 c
15-1363829853
Дмитрий С
2013-03-21 05:37
2013.08.25
XE3 можно ли сделать, чтобы некоторые модули


15-1363663611
Йети
2013-03-19 07:26
2013.08.25
где скачать BDE?


3-1292023741
Паша
2010-12-11 02:29
2013.08.25
Oracle 9i, получаю разные результаты update, не пойму, где косяк


2-1355222180
Darvin
2012-12-11 14:36
2013.08.25
Программная инсталляция драйвера


4-1266515606
leonidus
2010-02-18 20:53
2013.08.25
Определение типа ОС