Форум: "Начинающим";
Текущий архив: 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