TList проблема создания

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

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

TList проблема создания

Сообщение Юрий » 16.12.2022 12:08:57

Добрый день, всем

Господа, можете подсказать, почему код ниже в Lazarus выдаёт ошибку а в Delphi нет ?

Код: Выделить всё
procedure AAA;
var
  theClass: TClass;
  L: TList;
begin
  theClass := TList;
  L := TList(theClass.Create);     //  L := TList.Create;
  ShowMessage(L.ClassName);   
  if L.Count = 0 then    // <-- Access violation reading from address $0000000000000010.
    L.Add(nil);
end;   

Прямо какая-то досада непонятная... :(
Юрий
новенький
 
Сообщения: 11
Зарегистрирован: 03.04.2022 03:32:16

Re: TList проблема создания

Сообщение RRYTY » 16.12.2022 17:18:06

Наверно, потому что TClass нигде не определен.

А это вообще непонятно, что имеется ввиду:
Код: Выделить всё
theClass := TList;


Сразу предупрежу: про Delphi не знаю ничего.
RRYTY
постоялец
 
Сообщения: 187
Зарегистрирован: 25.12.2021 10:00:32

Re: TList проблема создания

Сообщение Юрий » 16.12.2022 17:43:46

Если бы он небыл бы определён, то тогда бы проект не скомпилился...

в Lazarus :
Код: Выделить всё
objpash.inc
...
     type
       TextFile = Text;

       { now the let's declare the base classes for the class object
         model. The compiler expects TObject and IUnknown to be defined
         first as forward classes }
       TObject = class;
       IUnknown = interface;

       TClass  = class of tobject;
       PClass  = ^tclass;   


Точно также как и в Delphi :
Код: Выделить всё
unit System;
...
type

  TObject = class;

  TClass = class of TObject;



>>А это вообще непонятно, что имеется ввиду: theClass := TList;

Это имеется ввиду переменная типа "Тип данных",
Стандартный тип данных,
в турбо паскаль появился а может и раньше...
Юрий
новенький
 
Сообщения: 11
Зарегистрирован: 03.04.2022 03:32:16

Re: TList проблема создания

Сообщение RRYTY » 16.12.2022 18:08:50

Тогда так:

Код: Выделить всё
L:= TList(theClass.Create).Create;
RRYTY
постоялец
 
Сообщения: 187
Зарегистрирован: 25.12.2021 10:00:32

Re: TList проблема создания

Сообщение DedFrend » 16.12.2022 20:13:30

а что там в uses?
DedFrend
постоялец
 
Сообщения: 156
Зарегистрирован: 25.11.2018 12:21:50

Re: TList проблема создания

Сообщение iskander » 16.12.2022 20:30:49

Юрий писал(а):Господа, можете подсказать, почему код ниже в Lazarus выдаёт ошибку а в Delphi нет ?
...
Прямо какая-то досада непонятная...

А которая Delphi, интересно?
Имхо подобные штуки могут работать только если конструктор базового класса виртуальный.
iskander
энтузиаст
 
Сообщения: 590
Зарегистрирован: 08.01.2012 18:43:34

Re: TList проблема создания

Сообщение Sharfik » 16.12.2022 21:50:32

Юрий писал(а):Господа, можете подсказать, почему код ниже в Lazarus выдаёт ошибку а в Delphi нет ?

Потому что Lazarus приличная IDE, а Delphi - нет. Delphi любит чтобы пользователь побольше мучался.

iskander писал(а):Имхо подобные штуки могут работать только если конструктор базового класса виртуальный.

Ого. Я утром читал чуть чуть, про эту обертку и там ничего об этом не было. Но правда.. работает код

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

TComponent
....
constructor Create(AOwner: TComponent); virtual;

procedure TForm1.Button3Click(Sender: TObject);
var
  theClass: TControlClass;
  L: TComboBox;
  T:TObject;
begin
  theClass := TComboBox;
  t        := theClass.Create(self);
  L := TComboBox(t);     //  L := TList.Create;
  ShowMessage(L.ClassName);
  if L.Items.Count = 0 then    // <-- Access violation reading from address $0000000000000010.
    L.Items.Add('-');
end;
Аватара пользователя
Sharfik
энтузиаст
 
Сообщения: 766
Зарегистрирован: 20.07.2013 01:04:30

Re: TList проблема создания

Сообщение Юрий » 17.12.2022 02:08:49

Sharfik писал(а):
Юрий писал(а):Господа, можете подсказать, почему код ниже в Lazarus выдаёт ошибку а в Delphi нет ?

Потому что Lazarus приличная IDE, а Delphi - нет. Delphi любит чтобы пользователь побольше мучался.

iskander писал(а):Имхо подобные штуки могут работать только если конструктор базового класса виртуальный.

Ого. Я утром читал чуть чуть, про эту обертку и там ничего об этом не было. Но правда.. работает код


>>Но правда.. работает код
Сделал по аналогии, работает (везде Laz64,D2007 32,XE8 64/32)

Код: Выделить всё
type
  TListClass = class of TList;

procedure TForm1.Button2Click(Sender: TObject);
var
  theClass: TListClass;
  L: TList;
  T: TObject;
begin
  theClass := TList;  // или наследники TList
  t        := theClass.Create;
  L        := TList(t);
  ShowMessage(t.ClassName);
  if L.Count = 0 then    // <-- Всё хорошо
    L.Add(nil);
...

Но есть момент что TListClass = class of TList; нужно самому определять. А в проекте где я выхватил эту ошибку, нужно будет это в кучи модулях прописывать что не очень... Это я для наглядности в одну процу засунул, подумаю…
Вам спасибо

>>Потому что Lazarus приличная IDE, а Delphi - нет. Delphi любит чтобы пользователь побольше мучался.
Тут я с вами не согласен. И та и та отличные среды, где-то в одной что-то удобнее, где-то в другой…
Тут вопрос выбора больше политически-идеологический… Моё личное мнение что после наступление примерного момента когда Убунта(и аналоги) стали по качеству луче чем Винда… Сначала Винда со своими обновлениями и инновациями пойдёт постепенно в Ж… А потом и Делфи потянется туда же… А для нас это процесс пойдёт быстрее, плоды начали всходить от санкций и импортозамещений…

Добавлено спустя 10 минут 10 секунд:
RRYTY писал(а):Тогда так:

Код: Выделить всё
L:= TList(theClass.Create).Create;


Удивительно но работает! (везде Laz64,D2007 32,XE8 64/32)

Код: Выделить всё
procedure TForm1.Button3Click(Sender: TObject);
var
  theClass: TClass;
  L: TList;
begin
  theClass := TList;

  //L := TList.Create;
  //L := TList(theClass.Create);
  L := TList(theClass.Create).Create;

  ShowMessage(L.ClassName);
  if L.Count = 0 then
    L.Add(nil);

  ShowMessage(IntToStr(L.Count));
  L.Free;
end;

Я, правда, не понимаю почему...
Утечек памяти нет
Как-то это противоречит логике. :shock:
Юрий
новенький
 
Сообщения: 11
Зарегистрирован: 03.04.2022 03:32:16

Re: TList проблема создания

Сообщение wavebvg » 17.12.2022 15:21:51

Юрий писал(а):
Sharfik писал(а):
Юрий писал(а):Удивительно но работает! (везде Laz64,D2007 32,XE8 64/32)


Всё зависит от менеджера памяти и включенных опций безопасности и т.п.

0. TObject.Create и TList.Create -- статические методы. Значит TList(theClass.Create); вызовет только TObject.Create выделит памяти для TObject.

1. TList(theClass.Create).Create; вызовет TObject.Create выделит памяти для TObject, после чего вызовет конструктор для TList.Create и попортит память за пределами класса.

2. В Дельфе TList класс в себе и ничего в конструкторе интересного не делает, в отличии от FPC-го, который, по сути, является делегированной обёрткой над TFPList.

3. Если обращение TFPList(nil).Count у Вас работает, т.е. чтение из адреса 0+Смещение FCount (+$10 судя из поста топикстартера) из TFPList, то нет AV, в противном случае есть.

PS Пост обновлён, т.к. TList(theClass.Create).Create; это сильно!
Последний раз редактировалось wavebvg 17.12.2022 17:45:26, всего редактировалось 1 раз.
wavebvg
постоялец
 
Сообщения: 354
Зарегистрирован: 28.02.2008 04:57:35

Re: TList проблема создания

Сообщение Sharfik » 17.12.2022 16:38:30

Юрий писал(а):>>Потому что Lazarus приличная IDE, а Delphi - нет. Delphi любит чтобы пользователь побольше мучался.
Тут я с вами не согласен. И та и та отличные среды, где-то в одной что-то удобнее, где-то в другой…
Тут вопрос выбора больше политически-идеологический… Моё личное мнение что после наступление примерного момента когда Убунта(и аналоги) стали по качеству луче чем Винда… Сначала Винда со своими обновлениями и инновациями пойдёт постепенно в Ж… А потом и Делфи потянется туда же… А для нас это процесс пойдёт быстрее, плоды начали всходить от санкций и импортозамещений…

При переходе с Delphi на Lazaasu о программировании узнаешь гораздо больше и код становится более продуманным.
Понятие "удобно" это путь к деградации. Вместо того чтобы учиться и изучать новое, люди упираются в одно какое то ПО и перестают развиваться. А дальше вместе с ними вся компания потенциально угасает. Сейчас это особенно заметно, когда люди вместо того чтобы попробовать что то новое начинают предлагать "давайте взломанный установим".

Юрий писал(а):L:= TList(theClass.Create).Create;

По сути бесполезный и не правильный код. Суть идеи TClass чтобы работать с абстрактным типом класса. Делать какие то манипуляции не ориентируясь на процедуры класса конкретного. А в указанном коде, это все теряется.
Аватара пользователя
Sharfik
энтузиаст
 
Сообщения: 766
Зарегистрирован: 20.07.2013 01:04:30

Re: TList проблема создания

Сообщение Alex2013 » 18.12.2022 00:20:01

Код: Выделить всё
theClass := TList;
:shock:
Присвоить экземпляру тип ? Это вообще как ????
===============================
Код: Выделить всё
  L:= TList(theClass.Create).Create;

А это вообще ИМХО ересь !
( Работать будет но в начале тупо сработает TClass(theClass).Create потом TList.Create; результат будет точно таким же как если сделать примерно так: L:= TList.Create; theClass:= TClass(L); ситуация чуть сложнее потому что theClass "переобувается в полете" но смысла в этой строке всеравно немного )

Имеет какой-то смысл только если нужно что-бы вначале отработал TClass.Create, а потом "поверх" TList.Create; но это по моему полный бред, потому что TList если я ничего не путаю наследник TClass и скорее всего и так вызывает код TClass.Create "по inherited " . :idea:
Зы
Не много подумал... Хм ! Идея понятна TClass как бы "базовый тип" но все равно странно.. Зачем нужны такие сложности ? :roll:
Alex2013
долгожитель
 
Сообщения: 2957
Зарегистрирован: 03.04.2013 11:59:44

Re: TList проблема создания

Сообщение Sharfik » 18.12.2022 02:39:39

Alex2013 писал(а):Зачем нужны такие сложности ?

Чтобы хакеры из Microsoft могли в любой момент ничего не зная программе управлять ею через абстрактные процедуры :roll: :mrgreen:
Аватара пользователя
Sharfik
энтузиаст
 
Сообщения: 766
Зарегистрирован: 20.07.2013 01:04:30

Re: TList проблема создания

Сообщение Юрий » 18.12.2022 04:41:50

Alex2013 писал(а):
Код: Выделить всё
theClass := TList;
:shock:
Присвоить экземпляру тип ? Это вообще как ????


Я не понимаю степень вашей удивлённости.
Ну это как бы базовые вещи языка..., можно сказать "типизированный указатель", вдруг если что, ещё можно в переменные функции и методы пихать...
как-то так...

Вот вам ссылочка на переводик
Ссылки на класс
https://pascal-study.blogspot.com/2012/ ... 9.html?m=1


Добавлено спустя 32 минуты 42 секунды:
RRYTY писал(а):Тогда так:

Код: Выделить всё
L:= TList(theClass.Create).Create;

Вам спасибо за интересный вариант
рабочий но спорный... В какойто момент думал распечатать повесить в рамку и в церьковь к экзорцистам бесов изгонять :twisted:
но после пояснений wavebvg и Alex2013 стало понятно как это работет...

и получается, что у себя я не смогу этим вариантов воспользоваться, т.к. эта "богадельня" по юнитам разным разбросана
    1. theClass.Create - выделит памяти для TObject (тут нет доступа к декларации, тип внутри переменной)
    2. в следующей функции if L.Count = 0 then L.Add(...);
    3. и только в следующей функции я буду иметь доступ к декларации TList-a и его наследников...
вся суть теряется

Добавлено спустя 9 минут 41 секунду:
wavebvg писал(а):
Всё зависит от менеджера памяти и включенных опций безопасности и т.п.

0. TObject.Create и TList.Create -- статические методы. Значит TList(theClass.Create); вызовет только TObject.Create выделит памяти для TObject.

1. TList(theClass.Create).Create; вызовет TObject.Create выделит памяти для TObject, после чего вызовет конструктор для TList.Create и попортит память за пределами класса.

2. В Дельфе TList класс в себе и ничего в конструкторе интересного не делает, в отличии от FPC-го, который, по сути, является делегированной обёрткой над TFPList.

3. Если обращение TFPList(nil).Count у Вас работает, т.е. чтение из адреса 0+Смещение FCount (+$10 судя из поста топикстартера) из TFPList, то нет AV, в противном случае есть.



Я считаю что это бага в FP
так как вся суть и прелесть использования Типа_ссылки_на_класс теряется

Добавлено спустя 16 минут 7 секунд:
Sharfik писал(а):
Юрий писал(а):>>Потому что Lazarus приличная IDE, а Delphi - нет. Delphi любит чтобы пользователь побольше мучался.
Тут я с вами не согласен. И та и та отличные среды, где-то в одной что-то удобнее, где-то в другой…
Тут вопрос выбора больше политически-идеологический… Моё личное мнение что после наступление примерного момента когда Убунта(и аналоги) стали по качеству луче чем Винда… Сначала Винда со своими обновлениями и инновациями пойдёт постепенно в Ж… А потом и Делфи потянется туда же… А для нас это процесс пойдёт быстрее, плоды начали всходить от санкций и импортозамещений…

При переходе с Delphi на Lazaasu о программировании узнаешь гораздо больше и код становится более продуманным.
Понятие "удобно" это путь к деградации. Вместо того чтобы учиться и изучать новое, люди упираются в одно какое то ПО и перестают развиваться. А дальше вместе с ними вся компания потенциально угасает. Сейчас это особенно заметно, когда люди вместо того чтобы попробовать что то новое начинают предлагать "давайте взломанный установим".

>>Понятие "удобно" это путь к деградации.
Что поделать деградация, регрессия, загнивание часть нашей жизни...
Ну вот иногда вам нужно забить гвоздь, вы идете в магаз и покупайте молоток, а можно купить и микроскоп, а можно купить завод, выплавить сталь и произвести молоток... У каждого своё "удобно"
Юрий
новенький
 
Сообщения: 11
Зарегистрирован: 03.04.2022 03:32:16

Re: TList проблема создания

Сообщение Alex2013 » 18.12.2022 07:54:20

Юрий писал(а):Я не понимаю степень вашей удивлённости.
Ну это как бы базовые вещи языка..., можно сказать "типизированный указатель", вдруг если что, ещё можно в переменные функции и методы пихать...
как-то так...

Ну и где вы там видели конструкцию "theClass := TList;"?
type TClass = class of TObject;
var AnyObj: TClass;
Это нормально . А var AnyObj: TClass; ... begin AnyObj := TObject;... ( или TList) нет .
Просто AnyObj у как был тип TClass так и остался . ( по моему там вообще ошибка вылезать должна)

Это же как если использовать нетипизированный параметры в процедуре/функции , "нетипизированный параметр" можно перевести к любому типу, но ПРИСВОИТЬ тип "в рунтайм режиме" по идее нельзя. :idea:


Если написать AnyObj := TObject.Create; то по сути язык просто глотает New и на самом деле делается AnyObj := New (TObject) и AnyObj.Create; написав AnyObj := TObject; мы не получаем ничего, возможно сработает New (TObject) но это очень сомнительно, а в случае AnyObj := TList; в fpc/лазарусе по умолчанию нужно написать приведение AnyObj := TClass (TList); В Дельфи куда более мягкое отношение к типизации по этому AnyObj := TList; может "проскочить" . Но даже так создать экземпляр класса БЕЗ вызова конструктора изрядная дикость .
Хм ! Возможно эта "лазейка" оставлена для использования классов "без конструктора но с деструктором" ( или возможности вызова "не стандартного" внешнего конструктора ) но все равно смотрится это очень бредово .
Alex2013
долгожитель
 
Сообщения: 2957
Зарегистрирован: 03.04.2013 11:59:44

Re: TList проблема создания

Сообщение Юрий » 18.12.2022 10:53:23

Alex2013 писал(а):
Юрий писал(а):Я не понимаю степень вашей удивлённости.
Ну это как бы базовые вещи языка..., можно сказать "типизированный указатель", вдруг если что, ещё можно в переменные функции и методы пихать...
как-то так...

Ну и где вы там видели конструкцию "theClass := TList;"?
type TClass = class of TObject;
var AnyObj: TClass;
Это нормально . А var AnyObj: TClass; ... begin AnyObj := TObject;... ( или TList) нет .
Просто AnyObj у как был тип TClass так и остался . ( по моему там вообще ошибка вылезать должна)

Это же как если использовать нетипизированный параметры в процедуре/функции , "нетипизированный параметр" можно перевести к любому типу, но ПРИСВОИТЬ тип "в рунтайм режиме" по идее нельзя. :idea:


Если написать AnyObj := TObject.Create; то по сути язык просто глотает New и на самом деле делается AnyObj := New (TObject) и AnyObj.Create; написав AnyObj := TObject; мы не получаем ничего, возможно сработает New (TObject) но это очень сомнительно, а в случае AnyObj := TList; в fpc/лазарусе по умолчанию нужно написать приведение AnyObj := TClass (TList); В Дельфи куда более мягкое отношение к типизации по этому AnyObj := TList; может "проскочить" . Но даже так создать экземпляр класса БЕЗ вызова конструктора изрядная дикость .
Хм ! Возможно эта "лазейка" оставлена для использования классов "без конструктора но с деструктором" ( или возможности вызова "не стандартного" внешнего конструктора ) но все равно смотрится это очень бредово .

>>Ну и где вы там видели конструкцию "theClass := TList;"?
CreateControl(TEdit, 'Edit1', 10, 10, 100, 20); // <-- здесь в стеке ControlClass : = TEdit


Почему вы считайте что присвоить тип "в рунтайм режиме" до создания объекта это прям недолжно быть возможно..?

Как я думаю, это должно работать, если
Код: Выделить всё
type
  TAAA = class(TObject) …
  TBBB = class(TAAA)  …
  TCCC = class(TBBB)  …

  TClass = class of TObject;

то
Код: Выделить всё
var
  theClass: TClass
begin
  theClass := TAAA;
  O := theClass.Create; // Создан экземпляр TAAA со своим переопределённым конструктором если он есть, не с констуктором TObject
  theClass := TBBB;
  O := theClass.Create; // Создан экземпляр TBBB со своим переопределённым конструктором
  theClass := TCCC;
  O := theClass.Create; // Создан экземпляр TCCC со своим переопределённым конструктором

И всё логично...
Юрий
новенький
 
Сообщения: 11
Зарегистрирован: 03.04.2022 03:32:16

След.

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

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

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

Рейтинг@Mail.ru