Наследованые классы и динамические массивы - > Баг

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

SovNarKom
постоялец
Сообщения: 389
Зарегистрирован: 28.05.2005 10:37:39
Откуда: Воронеж [vrn] [36]
Контактная информация:

Сообщение SovNarKom »

Это так и будет или лечится включением чего-нибудь? :o
Сразу скажу, что в Delphi всё ОК.
А FPC 2.0.0, 1.9.8 такая вот ерунда (в процессе работы acess violation...):

Код: Выделить всё

program Project1;

type

 TBaseC = class
  a,b,c: Integer;
  arra: Array of Cardinal;
 end;

 TOneClass = class(TBaseC)
  arr: Array of Cardinal;
 end;

 TMainClass = class
  A,B,C: Array of TBaseC;
 end;

 var SSS: TMainClass;
begin
 SSS:=TMainClass.Create;
 SetLength(SSS.A,1);
 SSS.A[0]:=TBaseC.Create; // кстати если TOneClass.Create - OK
 SetLength(TOneClass(SSS.A[0]).arr, 100000); // Хана! <--------------------------------
end.
Sniper
постоялец
Сообщения: 472
Зарегистрирован: 28.05.2005 13:02:42

Сообщение Sniper »

А в чём выражается сие ХАНА?
У меня в 2.1.1 вроде бы всё нормально..

Прочитал пост внимательнее: у меня никаких AV не наблюдается
Аватара пользователя
Romtek
постоялец
Сообщения: 190
Зарегистрирован: 22.05.2005 12:29:35
Откуда: Рамат Ган
Контактная информация:

Сообщение Romtek »

Присмотревшись к типам:

Код: Выделить всё

type

TBaseC = class
 a,b,c: Integer;
 arra: Array of Cardinal;
end;

TOneClass = class(TBaseC)
 arr: Array of Cardinal;
end;

TMainClass = class
 A,B,C: Array of TBaseC;
end;

Я подозреваю, что дело в именах A, B, C. Они перекрываются, хотя не знаю, верно ли это. Назови их другим именами.
SovNarKom
постоялец
Сообщения: 389
Зарегистрирован: 28.05.2005 10:37:39
Откуда: Воронеж [vrn] [36]
Контактная информация:

Сообщение SovNarKom »

Romtek
Неееее... они не перекрываются.

Тест №2 - > в 1.9.8 из под Лазаря runtime error 201, в 2.0.0 IDE - OK

Код: Выделить всё

program Project1;

type

 pTArr = ^TArr;
 TArr = Array [0..0] of Byte;

var
 SSS: pTArr;
 i: Integer = 99;
begin
 GetMem(SSS, 100000);
 SSS^[i]:=99; // < --------------------------- runtime error 201
 FreeMem(SSS);
end.

И этот метод не сработал...
Uniser
новенький
Сообщения: 46
Зарегистрирован: 13.05.2005 23:13:57
Откуда: Украина, Полтава

Сообщение Uniser »

Смотри чего делаешь (?):

Код: Выделить всё

SSS.A[0]:=TBaseC.Create; // кстати если TOneClass.Create - OK
SetLength(TOneClass(SSS.A[0]).arr, 100000); // Хана!

В массиве A могут храниться как TBaseC, так и его наследники TOneClass, но об этом должен помнить сам программист. Если ты создал TBaseC, а потом пытаешься найти в нём поле arr, объявленное в наследнике, так чего ты хочешь от Паскаля?!
Конечно нарушение!!!
SovNarKom
постоялец
Сообщения: 389
Зарегистрирован: 28.05.2005 10:37:39
Откуда: Воронеж [vrn] [36]
Контактная информация:

Сообщение SovNarKom »

Uniser
Ты прав,
НО в Delphi как-то работает... А ещё тут говорили что в FPC 2.1.1 :unsure:


Вот для чистоты эксперимента:

Код: Выделить всё

program Project1;
{$H+}
type

TBaseC = class end;

TOneClass = class(TBaseC)
 Ax: Array of Cardinal;
 Str: String;
 Card: Cardinal;
end;

TMainClass = class
 A:  TBaseC;
end;

var SSS: TMainClass;
begin
 SSS:=TMainClass.Create;

  {$DEFINE XAHA}

 {$IFDEF XAHA}
 SSS.A:=TBaseC.Create;
 TOneClass(SSS.A).Card:=1234567890;   // OK !!!!!!!!!!! <--------
 TOneClass(SSS.A).Str:='UPS'; // XAHA <--------------------------------
 SetLength(TOneClass(SSS.A).Ax, 100000); // XAHA <--------------------------------
 {$ENDIF}

 SSS.A:=TOneClass.Create;
 TOneClass(SSS.A).Card:=1234567890;   // OK
 TOneClass(SSS.A).Str:='UPS';// OK
 SetLength(TOneClass(SSS.A).Ax, 100000); // OK
end.
Uniser
новенький
Сообщения: 46
Зарегистрирован: 13.05.2005 23:13:57
Откуда: Украина, Полтава

Сообщение Uniser »

В Паскале не проверял, но в Делфи можно так:

Код: Выделить всё

  if SSS.A[0] is TOneClass then 
   SetLength(TOneClass(SSS.A[0]).arr, 100000)
  else WriteLn('Это другой класс.');
Uniser
новенький
Сообщения: 46
Зарегистрирован: 13.05.2005 23:13:57
Откуда: Украина, Полтава

Сообщение Uniser »

Может в Делфи не проверяется ошибка?
Не может программа создать TOneClass, когда её просят создать TBaseC.
Пробовал-ли заполнять массив созданный в Делфи?
SovNarKom
постоялец
Сообщения: 389
Зарегистрирован: 28.05.2005 10:37:39
Откуда: Воронеж [vrn] [36]
Контактная информация:

Сообщение SovNarKom »

Uniser
Можно, но мне это не поможет :(

Я код ^ поправил малость - если у наследника поле имеет фиксированый размер - всё нормально.
SovNarKom
постоялец
Сообщения: 389
Зарегистрирован: 28.05.2005 10:37:39
Откуда: Воронеж [vrn] [36]
Контактная информация:

Сообщение SovNarKom »

Uniser
У меня в Delphi на этом многое(!) работает и ни разу не сваливалось в acess violation... А это просто пример...
Uniser
новенький
Сообщения: 46
Зарегистрирован: 13.05.2005 23:13:57
Откуда: Украина, Полтава

Сообщение Uniser »

Ошибка не выскакивает, но ты всё равно портишь информацию в памяти.
Проблема связана с ограниченностью функции проверяющей нарушение доступа, которая не видит нарушения в

Код: Выделить всё

 SSS.A:=TBaseC.Create;
 TOneClass(SSS.A).Card:=1234567890;

На самом деле таким присваиванием ты можешь испортить значения в других объектах, также как запросто можешь потерять его в результате другой команды.
SovNarKom
постоялец
Сообщения: 389
Зарегистрирован: 28.05.2005 10:37:39
Откуда: Воронеж [vrn] [36]
Контактная информация:

Сообщение SovNarKom »

Uniser
Скорее всего ты прав... :)
Uniser
новенький
Сообщения: 46
Зарегистрирован: 13.05.2005 23:13:57
Откуда: Украина, Полтава

Сообщение Uniser »

Если у наследника будет много полей то в конце концов таким присваиванием

Код: Выделить всё

 SSS.A:=TBaseC.Create;
 TOneClass(SSS.A).Card:=1234567890;

ты получишь AV
SovNarKom
постоялец
Сообщения: 389
Зарегистрирован: 28.05.2005 10:37:39
Откуда: Воронеж [vrn] [36]
Контактная информация:

Сообщение SovNarKom »

Да вспомнил! В Delphi тоже были проблемы, я отказался от динамических массивов... да это конечно правильно при создании класса памяти выделяется только для него, да.

А вот по поводу второго примера?
Uniser
новенький
Сообщения: 46
Зарегистрирован: 13.05.2005 23:13:57
Откуда: Украина, Полтава

Сообщение Uniser »

У меня ни в Делфи ни в Лазарусе ни в Паскале не выдаёт никаких ошибок.
Ответить