Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2013.08.25;
Скачать: [xml.tar.bz2];

Вниз

Глюк в динамическом массиве 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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.55 MB
Время: 0.004 c
4-1266740974
leonidus
2010-02-21 11:29
2013.08.25
Определение разрядности программы


15-1364131639
TUser
2013-03-24 17:27
2013.08.25
Пенроуз в Политехническом музее


15-1363729018
Германн
2013-03-20 01:36
2013.08.25
Windows 7 trial


15-1364034591
Artem
2013-03-23 14:29
2013.08.25
Просмотр файлов cookie (логины пароли) в firefox offline


8-1232368698
golovanog
2009-01-19 15:38
2013.08.25
Проблема источников в OpenAL (проиграть 999 семплов одновременно)





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский