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

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

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

Сообщение SovNarKom » 26.06.2005 23:10:38

Это так и будет или лечится включением чего-нибудь? :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.
SovNarKom
постоялец
 
Сообщения: 389
Зарегистрирован: 28.05.2005 10:37:39
Откуда: Воронеж [vrn] [36]

Сообщение Sniper » 27.06.2005 00:01:01

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

Прочитал пост внимательнее: у меня никаких AV не наблюдается
Sniper
постоялец
 
Сообщения: 472
Зарегистрирован: 28.05.2005 13:02:42

Сообщение Romtek » 27.06.2005 01:12:03

Присмотревшись к типам:
Код: Выделить всё
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. Они перекрываются, хотя не знаю, верно ли это. Назови их другим именами.
Аватара пользователя
Romtek
постоялец
 
Сообщения: 190
Зарегистрирован: 22.05.2005 12:29:35
Откуда: Рамат Ган

Сообщение SovNarKom » 27.06.2005 11:03:21

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.

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

Сообщение Uniser » 27.06.2005 11:33:37

Смотри чего делаешь (?):
Код: Выделить всё
SSS.A[0]:=TBaseC.Create; // кстати если TOneClass.Create - OK
SetLength(TOneClass(SSS.A[0]).arr, 100000); // Хана!

В массиве A могут храниться как TBaseC, так и его наследники TOneClass, но об этом должен помнить сам программист. Если ты создал TBaseC, а потом пытаешься найти в нём поле arr, объявленное в наследнике, так чего ты хочешь от Паскаля?!
Конечно нарушение!!!
Uniser
новенький
 
Сообщения: 46
Зарегистрирован: 13.05.2005 23:13:57
Откуда: Украина, Полтава

Сообщение SovNarKom » 27.06.2005 11:37:36

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.
SovNarKom
постоялец
 
Сообщения: 389
Зарегистрирован: 28.05.2005 10:37:39
Откуда: Воронеж [vrn] [36]

Сообщение Uniser » 27.06.2005 11:38:27

В Паскале не проверял, но в Делфи можно так:
Код: Выделить всё
 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 » 27.06.2005 11:43:02

Может в Делфи не проверяется ошибка?
Не может программа создать TOneClass, когда её просят создать TBaseC.
Пробовал-ли заполнять массив созданный в Делфи?
Uniser
новенький
 
Сообщения: 46
Зарегистрирован: 13.05.2005 23:13:57
Откуда: Украина, Полтава

Сообщение SovNarKom » 27.06.2005 11:43:24

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

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

Сообщение SovNarKom » 27.06.2005 11:45:11

Uniser
У меня в Delphi на этом многое(!) работает и ни разу не сваливалось в acess violation... А это просто пример...
SovNarKom
постоялец
 
Сообщения: 389
Зарегистрирован: 28.05.2005 10:37:39
Откуда: Воронеж [vrn] [36]

Сообщение Uniser » 27.06.2005 11:49:36

Ошибка не выскакивает, но ты всё равно портишь информацию в памяти.
Проблема связана с ограниченностью функции проверяющей нарушение доступа, которая не видит нарушения в
Код: Выделить всё
SSS.A:=TBaseC.Create;
TOneClass(SSS.A).Card:=1234567890;

На самом деле таким присваиванием ты можешь испортить значения в других объектах, также как запросто можешь потерять его в результате другой команды.
Uniser
новенький
 
Сообщения: 46
Зарегистрирован: 13.05.2005 23:13:57
Откуда: Украина, Полтава

Сообщение SovNarKom » 27.06.2005 11:51:39

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

Сообщение Uniser » 27.06.2005 11:51:55

Если у наследника будет много полей то в конце концов таким присваиванием
Код: Выделить всё
SSS.A:=TBaseC.Create;
TOneClass(SSS.A).Card:=1234567890;

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

Сообщение SovNarKom » 27.06.2005 11:55:59

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

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

Сообщение Uniser » 27.06.2005 12:11:02

У меня ни в Делфи ни в Лазарусе ни в Паскале не выдаёт никаких ошибок.
Uniser
новенький
 
Сообщения: 46
Зарегистрирован: 13.05.2005 23:13:57
Откуда: Украина, Полтава

След.

Вернуться в Free Pascal Compiler

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 23

Рейтинг@Mail.ru