OberonCore https://forum.oberoncore.ru/ |
|
NEW в процедуре. https://forum.oberoncore.ru/viewtopic.php?f=29&t=5881 |
Страница 1 из 2 |
Автор: | prospero78 [ Пятница, 02 Сентябрь, 2016 17:35 ] |
Заголовок сообщения: | NEW в процедуре. |
Уважаемые коллеги! Совершенно очевидно, что я не понимаю, как работает такой кусок: 1. Создаю статический указатель на запись. 2. Передаю в процедуру этот указатель, где в процедуре делаю NEW(указатель) и все остальные первоначальные манипуляции. 3. При возврате из процедуры BlackBox ругается на NIL. Т.е. фактически, как мой указатель был инициирован NIL, так и остался. Подскажите правильный порядок действий. Если это возможно. Может, как-то разыменование сделать. Или RETURN с указателем через локальный VAR (хотя, на сколько я понимаю, такой указатель будет на стеке?) Короче, надеюсь только на вас)) |
Автор: | Александр Ильин [ Пятница, 02 Сентябрь, 2016 17:48 ] |
Заголовок сообщения: | Re: NEW в процедуре. |
Код в студию! Не понятно, что такое "статический указатель". Не понятно, передаётся ли указатель в процедуру по ссылке или по значению. |
Автор: | prospero78 [ Пятница, 02 Сентябрь, 2016 18:12 ] |
Заголовок сообщения: | Re: NEW в процедуре. |
Примерно так: Код: MODULE a1 TYPE tpRecord = POINTER TO RECORD a:BYTE END; PROCEDURE Init*(tpr_:tpRecord; a_:BYTE); BEGIN NEW(tpr_); tpr_.a:=a_ END Init; END a1. Код: MODULE a2; IMPORT a1; VAR myVar: a1.tpRecord; BEGIN a1.Init(myVar,0) END a1. Подозреваю, что где-то что-то я забыл)) Подставить VAR перед указателем в процедуре? |
Автор: | Alexander Shiryaev [ Пятница, 02 Сентябрь, 2016 18:20 ] |
Заголовок сообщения: | Re: NEW в процедуре. |
да |
Автор: | prospero78 [ Пятница, 02 Сентябрь, 2016 18:33 ] |
Заголовок сообщения: | Re: NEW в процедуре. |
Хорошо. Вопрос в догонку. Я наследую через указатель -- указатель на расширяемую запись. 1. Так можно? 2. Как базовому указателю грамотно NEW устроить? |
Автор: | Илья Ермаков [ Пятница, 02 Сентябрь, 2016 18:43 ] |
Заголовок сообщения: | Re: NEW в процедуре. |
Давайте код, на слух невозможно понять ) |
Автор: | prospero78 [ Пятница, 02 Сентябрь, 2016 18:52 ] |
Заголовок сообщения: | Re: NEW в процедуре. |
Код: TYPE tpGrad* = POINTER TO EXTENSIBLE RECORD (mTf.tpFaze) END; PROCEDURE Init(VAR grad_:tpGrad; faze_:BYTE); BEGIN NEW(grad_); mTf.Init(grad_.????) (* вот здесь как быть -- не догоняю *) END Init; Или здесь наследование не прокатывает? |
Автор: | Иван Денисов [ Пятница, 02 Сентябрь, 2016 19:08 ] | ||
Заголовок сообщения: | Re: NEW в процедуре. | ||
prospero78 писал(а): Хорошо. Вопрос в догонку. Я наследую через указатель -- указатель на расширяемую запись. 1. Так можно? 2. Как базовому указателю грамотно NEW устроить? Вот старый примерчик. Вроде бы он был по книге: Фримен Э. и др. Паттерны проектирования. Санкт-Петербург: Питер, 2011. 656 с. Тут не только фабрика, но и еще "нечто" в стиле ББ. Код: MODULE MyTest;
IMPORT Log; TYPE Animal = POINTER TO ABSTRACT RECORD next: Animal END; Cat = POINTER TO RECORD (Animal) END; Dog = POINTER TO RECORD (Animal) END; Directory = POINTER TO RECORD root: Animal END; VAR dir: Directory; PROCEDURE (d: Directory) Add (a: Animal), NEW; VAR tmp: Animal; BEGIN IF d.root = NIL THEN d.root := a ELSE tmp := d.root; WHILE tmp.next # NIL DO tmp := tmp.next END; tmp.next := a END END Add; PROCEDURE (a: Animal) FeedMilk, NEW, ABSTRACT; PROCEDURE (a: Cat) FeedMilk; BEGIN Log.String("Mmm!"); Log.Ln; END FeedMilk; PROCEDURE (a: Dog) FeedMilk; BEGIN Log.String("No thanks!"); Log.Ln; END FeedMilk; (* Фабрика объетов *) PROCEDURE (d: Directory) New (type: INTEGER): Animal, NEW; VAR a: Animal; cat: Cat; dog: Dog; BEGIN CASE type OF 1: NEW(cat); a := cat; | 2 : NEW(dog); a := dog; ELSE END; dir.Add(a); RETURN a END New; PROCEDURE Test*; VAR a: Animal; BEGIN dir.root := NIL; (* add animals *) a := dir.New(1); a := dir.New(2); a := dir.root; WHILE a # NIL DO a.FeedMilk; a := a.next END END Test; BEGIN NEW(dir); END MyTest. MyTest.Test
|
Автор: | Илья Ермаков [ Пятница, 02 Сентябрь, 2016 20:48 ] |
Заголовок сообщения: | Re: NEW в процедуре. |
VAR-аргумент указательного типа должен в точности соответствовать типу формального параметра. |
Автор: | prospero78 [ Суббота, 03 Сентябрь, 2016 10:17 ] |
Заголовок сообщения: | Re: NEW в процедуре. |
У меня мысль пришла, что можно попробовать сделать через CASE type_ OF. Но, это не очень элегантно, имхо. При добавлении нового типа, поверх базового типа придётся циферки придумывать. В Компонентном Паскале есть прямая проверка типа, так что в процедуру (теоретически) достаточно передавать просто базовый класс. И посетила меня ещё одна мысль: а незачем мне все типы определять как указатели. Ведь мне важен только верхний уровень. только он и должен быть указателем. При присвоении NIL всё остальное сборщик мусора подгребёт по полной программе)) Короче, спасибо всем за подсказки, буду пробовать) Я правильно понимаю, что фактически, в своём примере я предлагаю реализацию фабрики классов? |
Автор: | Илья Ермаков [ Суббота, 03 Сентябрь, 2016 12:28 ] |
Заголовок сообщения: | Re: NEW в процедуре. |
Вы фабрики используйте, фабрики! |
Автор: | Иван Денисов [ Суббота, 03 Сентябрь, 2016 16:39 ] |
Заголовок сообщения: | Re: NEW в процедуре. |
prospero78 писал(а): Я правильно понимаю, что фактически, в своём примере я предлагаю реализацию фабрики классов? Нет, у тебя не фабрика. Фабрику смотри в моем примере Directory. |
Автор: | prospero78 [ Суббота, 03 Сентябрь, 2016 18:08 ] |
Заголовок сообщения: | Re: NEW в процедуре. |
Я понял отличие. Принимает что угодно, а на выходе объект. Не, у меня задача попроще. Количество объектов известно заранее. И их нужно уничтожать по окончанию дорасчёта. А уничтожить можно только через NIL в указатели. Тогда модули будут выгружаться как положено. Поэтому, мне указатель нужен только на самом верху. Вниз с ними работать смысла не имеет. Или мне для выгрузки модулей, это не поможет?))) |
Автор: | Иван Денисов [ Суббота, 03 Сентябрь, 2016 18:18 ] |
Заголовок сообщения: | Re: NEW в процедуре. |
prospero78 писал(а): Я понял отличие. Принимает что угодно, а на выходе объект. Не, у меня задача попроще. Количество объектов известно заранее. И их нужно уничтожать по окончанию дорасчёта. А уничтожить можно только через NIL в указатели. Тогда модули будут выгружаться как положено. Поэтому, мне указатель нужен только на самом верху. Вниз с ними работать смысла не имеет. Или мне для выгрузки модулей, это не поможет?))) Никогда в ручную не приходилось присваивать куда-то NIL. КП сам видит, когда объекты больше не нужны. Если объект больше не используется, например, он удален из списка, то на него нигде нет ссылок и его сборщик сам удалит. Задача главная это выгружать модули? |
Автор: | prospero78 [ Суббота, 03 Сентябрь, 2016 19:01 ] |
Заголовок сообщения: | Re: NEW в процедуре. |
Да, именно так, Вань. Но у меня модули не выгружаются сами. В том-то и фишка. Вот думаю, может, через указатели сейчас сделаю, что-то изменится)) Через NIL то уже явно ресурсы освобождаться будут)). Ну и с точки зрения надёжности, мне не помешает указатели в добровольно-принудительном порядке в NIL приводить. Вообще, у меня задумка есть вообще все объекты типа в конфиг собрать в одном месте)) Тогда все модули будут выгружаться, кроме этого конфига) Выгрузка нужна чтобы была возможность подредактировать модуль, скомпилять и снова в бой. А так приходится всю среду перезапускать. И я так подозреваю, что это не правильно от слова "совсем". |
Автор: | Иван Денисов [ Суббота, 03 Сентябрь, 2016 19:25 ] |
Заголовок сообщения: | Re: NEW в процедуре. |
Модуль не выгружается не из-за объектов. А из-за того, что ты где-то его импортировал. Тут жесткое правило, что модули выгружаются только если нет других модулей, где он импортирован. Так что тебе нельзя этот модуль использовать в секции импорта нигде, только так. Это на самом деле не очень сложно, вот тут есть пара примеров http://gitlab.molpit.org/bindings/sdl2 Модуль Sdl2StdWin во время "ручного" импорта в примерах Obx* устанавливает себя как реализацию абстрактного интерфейса. Код: (* Load realisations for current platform *)
IF Dialog.IsWindows() THEN ASSERT(Kernel.ThisMod('Sdl2StdWin') # NIL, 20) ELSIF Dialog.IsLinux() THEN ASSERT(Kernel.ThisMod('Sdl2StdLin') # NIL, 20) ELSE HALT(20) END; |
Автор: | prospero78 [ Суббота, 03 Сентябрь, 2016 19:42 ] |
Заголовок сообщения: | Re: NEW в процедуре. |
Это понятно, что если один модуль импортирует другой, то, тот который уровнем глубже не может быть выгружен. Тут фишка получается, что какой-то модуль из верхнего уровня продолжает в памяти висеть, даже после закрытия окна. Так вот непонятно, почему такой модуль остаётся в памяти, если его ничего не держит, и соответственно, все остальные модули уровнями ниже? |
Автор: | Иван Денисов [ Суббота, 03 Сентябрь, 2016 19:55 ] |
Заголовок сообщения: | Re: NEW в процедуре. |
prospero78 писал(а): Это понятно, что если один модуль импортирует другой, то, тот который уровнем глубже не может быть выгружен. Тут фишка получается, что какой-то модуль из верхнего уровня продолжает в памяти висеть, даже после закрытия окна. Так вот непонятно, почему такой модуль остаётся в памяти, если его ничего не держит, и соответственно, все остальные модули уровнями ниже? А модули сами, как я понял, вообще не выгружаются... Я думал по началу, что было бы логично, если бы они сами выгружались, но не тут то было. |
Автор: | prospero78 [ Суббота, 03 Сентябрь, 2016 22:21 ] |
Заголовок сообщения: | Re: NEW в процедуре. |
Но раз подсчёт модулей ведётся, и ссылки на них, всё-таки должна быть команды выгрузки? Ведь БлэкБокс как-то их сам выгружает?? Впрочем.... Что мне мешает открыть команду меню?)))) |
Автор: | prospero78 [ Суббота, 03 Сентябрь, 2016 23:09 ] |
Заголовок сообщения: | Re: NEW в процедуре. |
Не побоялся залезть в Kernel, и оказалась задача с принудительной выгрузкой модулей вполне решаема! Вот что я родил: Код: PROCEDURE Модуль_выгрузить(IN мод_: ARRAY OF CHAR); VAR модуль: мЯдро.Module; BEGIN модуль:=мЯдро.ThisMod(мод_); мЯдро.UnloadMod(модуль) END Модуль_выгрузить; где, мЯдро := Kernel. Не знаю, на сколько это безопасно, на зато проверено на 4-х модулях -- работает!!!))) |
Страница 1 из 2 | Часовой пояс: UTC + 3 часа |
Powered by phpBB® Forum Software © phpBB Group https://www.phpbb.com/ |