Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Глюк в динамическом массиве Delphi [D2]


Страницы:   1 2

AlexA ©   (2012-12-14 15:05:00) 

Есть структура
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
Как с этим бороться то?


AlexA   (2012-12-16 21:34:00) [1]

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


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

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


AlexA   (2012-12-16 20:33:00) [3]

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


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

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

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


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

memproof, fastmm


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


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

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


AlexA   (2012-12-16 16:12:00) [7]

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

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


O'ShinW   (2012-12-16 10:48:00) [8]

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


KilkennyCat   (2012-12-15 23:54:00) [9]

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


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


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


Это спьяну


KilkennyCat   (2012-12-15 22:09:00) [11]

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


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

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


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

> 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:19:00) [14]


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

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


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

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

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


KilkennyCat   (2012-12-15 20:15:00) [16]

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


begin...end   (2012-12-15 19:42:00) [17]

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

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


KilkennyCat   (2012-12-15 19:35:00) [18]


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

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


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

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


begin...end   (2012-12-15 19:22:00) [20]

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

> смотри [9]

Это вряд ли.


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо