OberonCore https://forum.oberoncore.ru/ |
|
Процедурные типы https://forum.oberoncore.ru/viewtopic.php?f=29&t=6870 |
Страница 2 из 2 |
Автор: | Александр К [ Понедельник, 14 Ноябрь, 2022 15:12 ] |
Заголовок сообщения: | Re: Процедурные типы |
adimetrius писал(а): При выгрузке модулей та же проблема вообще с любыми указателями: выгрузили М, а переменная п: М.Т осталась, и попытки вызвать связанные с М.Т процедуры - тоже в никуда. И в текущей реализации (в линукс) последствия непредсказуемы, т.к. платформенная защита памяти от исполнения не используется. Но, как я понимаю идеологию ББ: выгрузка модулей - действие этапа разработки, в "боевой системе" этого делать не следует; поэтому соответствующие защиты не реализованы. В BlackBox`е для Windows импортируемый модуль можно выгрузить только после импортирующего. Обычно я использую абстрактные процедуры когда надо описать что-то общее, универсальное, детали которого ещё не известны. Например, я абстрактные процедуры использовал для сортировки, когда сортирующая программа ничего не знает о ключах, по которым сравниваются два элемента: Код: CONST AsmallerB = 1; AequalB = 2; AlargerB = 3; TYPE Element = POINTER TO ABSTRACT RECORD END; List = RECORD elements: ARRAY 100 OF Element; END; PROCEDURE (a: Element) Compare* (b: Element): BYTE, NEW, ABSTRACT; PROCEDURE (VAR obj: List) Sort*, NEW; VAR i: INTEGER; ... BEGIN ... CASE obj.elements[i].Compare (obj.elements[i+1]) OF AsmallerB: ... | AequalB: ... | AlargerB: ... ELSE ... END ... END Sort; Мне сейчас непонятно, как пользоваться процедурой, передаваемой как параметр. А именно, как указать тело этой процедуры, и как её вызвать? Она что, вызывается при присваивании? |
Автор: | Comdiv [ Вторник, 15 Ноябрь, 2022 02:45 ] |
Заголовок сообщения: | Re: Процедурные типы |
Александр К писал(а): В BlackBox`е для Windows импортируемый модуль можно выгрузить только после импортирующего. Как раз благодаря косвенности ссылка на тип выгруженного модуля и может остаться у кода модуля, который не импортировал его напрямую. Код: MODULE A; IMPORT Log; TYPE T* = POINTER TO EXTENSIBLE RECORD END; VAR v: T; PROCEDURE (v: T) Do*, NEW, EXTENSIBLE; BEGIN Log.String("A.T.Do"); Log.Ln END Do; PROCEDURE Do*; BEGIN v.Do END Do; PROCEDURE Set*(new: T); BEGIN v := new END Set; BEGIN NEW(v) END A. (!)A.Do Код: MODULE B;
IMPORT A, Log; TYPE T = POINTER TO RECORD(A.T) END; PROCEDURE (v: T) Do*; BEGIN Log.String("B: T.Do"); Log.Ln END Do; PROCEDURE Install*; VAR v: T; BEGIN NEW(v); A.Set(v) END Install; END B. (!)B.Install (!)DevDebug.Unload |
Автор: | Comdiv [ Вторник, 15 Ноябрь, 2022 03:02 ] |
Заголовок сообщения: | Re: Процедурные типы |
Александр К писал(а): Мне сейчас непонятно, как пользоваться процедурой, передаваемой как параметр. А именно, как указать тело этой процедуры, и как её вызвать? Она что, вызывается при присваивании? Что в случае с процедурой, что в случае с записью сравнитель лучше вынести в отдельную переменную, потому что одни и те же элементы может понадобиться сравнивать по разному. Сам же элемент мог бы выдавать некий сравнитель по умолчанию.Код: TYPE Element* = POINTER TO ABSTRACT RECORD END; Compare* = PROCEDURE (a, b: Element): INTEGER; PROCEDURE (a: Element) DefaultComparator*(): Compare, NEW, ABSTRACT; PROCEDURE Sort*(elements: ARRAY OF Element; compare: Compare); VAR i: INTEGER; ... BEGIN IF compare = NIL THEN compare := elements[0].DefaultComparator(); END; ... CASE compare(obj.elements[i], obj.elements[i+1]) OF -1: ... | 0: ... | 1: ... END ... END Sort; Код: TYPE
Element* = POINTER TO ABSTRACT RECORD END; Compare* = POINTER TO ABSTRACT RECORD END; PROCEDURE (c: Compare) Do*(a, b: Element): INTEGER, NEW, ABSTRACT; PROCEDURE (a: Element) DefaultComparator*(): Compare, NEW, ABSTRACT; PROCEDURE Sort*(elements: ARRAY OF Element; compare: Compare); VAR i: INTEGER; ... BEGIN IF compare = NIL THEN compare := elements[0].DefaultComparator(); END; ... CASE compare.Do(obj.elements[i], obj.elements[i+1]) OF -1: ... | 0: ... | 1: ... END ... END Sort; |
Автор: | adimetrius [ Среда, 16 Ноябрь, 2022 13:24 ] |
Заголовок сообщения: | Re: Процедурные типы |
Александр К писал(а): Мне сейчас непонятно, как пользоваться процедурой, передаваемой как параметр. А именно, как указать тело этой процедуры, и как её вызвать? Она что, вызывается при присваивании? Код: MODULE M; TYPE Proc = PROCEDURE (x: INTEGER; ch: CHAR): BOOLEAN; PROCEDURE Lss (x: INTEGER; ch: CHAR): BOOLEAN; BEGIN RETURN ORD(ch) < x END A; PROCEDURE Gtr (x: INTEGER; ch: CHAR): BOOLEAN; BEGIN RETURN ORD(ch) > x END B; PROCEDURE Do (x: INTEGER; ch: CHAR; action: Proc); VAR res: BOOLEAN; BEGIN ASSERT(action # NIL, 20); (* процедурные переменные можно сравнивать с NIL *) res := action(x, ch); (* вызов процедуры, присвоенной параметру action *) res := action(x + 1, ch) (* еще раз вызов процедуры, присвоенной параметру action *) END Do; PROCEDURE P; BEGIN Do(1, 'A', Lss); (* процедура Lss присваивается параметру action. Но здесь Lss не вызывается *) Do(1, 'A', Gtr); (* процедура Gtr присваивается параметру action. Но здесь Gtr не вызывается *) Do(1, 'A', NIL) (* NIL присваивается параметру action. Это кончится авостом 20, т.к. Do на такое не рассчитана *) END P; END M. Именовать процедурные типы необязательно: PROCEDURE P (do: PROCEDURE (x: INTEGER)), поскольку в отношении них, как видно, действуют правила структурной совместимости, о которых писал Comdiv. |
Автор: | adimetrius [ Среда, 16 Ноябрь, 2022 13:32 ] |
Заголовок сообщения: | Re: Процедурные типы |
Comdiv писал(а): adimetrius писал(а): При выгрузке модулей та же проблема вообще с любыми указателями: выгрузили М, а переменная п: М.Т осталась, и попытки вызвать связанные с М.Т процедуры - тоже в никуда. И в текущей реализации (в линукс) последствия непредсказуемы, т.к. платформенная защита памяти от исполнения не используется. Но, как я понимаю идеологию ББ: выгрузка модулей - действие этапа разработки, в "боевой системе" этого делать не следует; поэтому соответствующие защиты не реализованы. Тут, видимо, дело в трактовке процедурного типа - если его воплощать максимально прямо, а не как более сложный неявный объект, то переменная процедурного типа будет просто указателем на код без привязки к модулю с возможностью вызова непонятно чего. У объекта же потенциально больше возможностей по предотвращению обращения куда попало, пусть и с последствиями для кода, который пытается это делать.Это, конечно, вопрос реализации, а не самого языка. Большей устойчивости можно добиться и без объекта, а за счет запрета на исполнение в адресных промежутках, в которых располагался текст модуля, после его выгрузки. Если, конечно, платформа предусматривает такие средства. |
Автор: | adimetrius [ Среда, 16 Ноябрь, 2022 13:37 ] |
Заголовок сообщения: | Re: Процедурные типы |
Александр К писал(а): adimetrius писал(а): При выгрузке модулей та же проблема вообще с любыми указателями: выгрузили М, а переменная п: М.Т осталась, и попытки вызвать связанные с М.Т процедуры - тоже в никуда. И в текущей реализации (в линукс) последствия непредсказуемы, т.к. платформенная защита памяти от исполнения не используется. Но, как я понимаю идеологию ББ: выгрузка модулей - действие этапа разработки, в "боевой системе" этого делать не следует; поэтому соответствующие защиты не реализованы. В BlackBox`е для Windows импортируемый модуль можно выгрузить только после импортирующего. В любом ББ, конечно, так же. Но. Модуль М может быть загружен, даже если его ни один другой модуль не импортирует. Например, М реализует некий вид В, я открываю вид типа В в окне, и затем выгружаю М. Выгрузка позволяется, поскольку никто не импортирует М; а следом возникает авария (или "зависание"), поскольку система вызывает процедуры открытого в окне вида типа М.В. |
Автор: | Comdiv [ Среда, 16 Ноябрь, 2022 21:59 ] |
Заголовок сообщения: | Re: Процедурные типы |
adimetrius писал(а): Это, конечно, вопрос реализации, а не самого языка. Отчего же, для дизайна таких языков как Oberon не принято прятать что-то более сложное за чем-то более простым, иначе, вместо исключения процедурного типа, можно было говорить о его представлении как синтаксического сахара для небольшой записи.Цитата: Большей устойчивости можно добиться и без объекта, а за счет запрета на исполнение в адресных промежутках, в которых располагался текст модуля, после его выгрузки. Если, конечно, платформа предусматривает такие средства. Большая "устойчивость" за счёт исчерпания адресного пространства с учётом прошлого, да и пока ещё текущего состояния Blackbox.
|
Автор: | adimetrius [ Четверг, 17 Ноябрь, 2022 00:04 ] |
Заголовок сообщения: | Re: Процедурные типы |
Comdiv писал(а): Большая "устойчивость" за счёт исчерпания адресного пространства с учётом прошлого, да и пока ещё текущего состояния Blackbox. Да; у такого решения, как и любого, есть свой "за счет". Исчерпание адресного пространства м.б. проблемой для долгоживущих активаций ББ. А выгрузка модулей, как я писал выше - операция времени разработки, т.е. используется в АРМ программиста. Является ли АРМ долгоживущей активацией? Вряд ли. Организовать "исчерпывающую (адресное простанство)" защиту от выполнения мусорных байт легче, чем синтаксический сахар, т.к. не нужно править компилятор и среду выполнения; достаточно только среду. Другое дело, если вообразить такую задачу: неограниченно долго работающий исполнитель на базе ББ получает команды, в ответ загружает некие модули, а по завершении команд или сессий может выгружать ненужные модули; и такой сервер должен работать неограниченно долго. Веб-сервер ББ-приложений, короче говоря. Тогда, вероятно, нельзя разбрасываться адресным пространством. |
Автор: | Comdiv [ Четверг, 17 Ноябрь, 2022 03:04 ] |
Заголовок сообщения: | Re: Процедурные типы |
adimetrius писал(а): А выгрузка модулей, как я писал выше - операция времени разработки, т.е. используется в АРМ программиста.Является ли АРМ долгоживущей активацией? Вряд ли. Вы-то писали, но почему-то забыли работу с плагинами, да и в долгоживущем АРМ не вижу ничего необычного, если конечно, оно не будет вынуждать себя постоянно перезапускать.adimetrius писал(а): Другое дело, если вообразить Вы так пишете, как-будто это не банальщина, а ведь BlackBox - это ОС, пусть и недо, если такое определение кого-то коробит.
|
Автор: | SovietPony [ Суббота, 31 Декабрь, 2022 19:18 ] |
Заголовок сообщения: | Re: Процедурные типы |
adimetrius писал(а): Comdiv писал(а): adimetrius писал(а): При выгрузке модулей та же проблема вообще с любыми указателями: выгрузили М, а переменная п: М.Т осталась, и попытки вызвать связанные с М.Т процедуры - тоже в никуда. И в текущей реализации (в линукс) последствия непредсказуемы, т.к. платформенная защита памяти от исполнения не используется. Но, как я понимаю идеологию ББ: выгрузка модулей - действие этапа разработки, в "боевой системе" этого делать не следует; поэтому соответствующие защиты не реализованы. Тут, видимо, дело в трактовке процедурного типа - если его воплощать максимально прямо, а не как более сложный неявный объект, то переменная процедурного типа будет просто указателем на код без привязки к модулю с возможностью вызова непонятно чего. У объекта же потенциально больше возможностей по предотвращению обращения куда попало, пусть и с последствиями для кода, который пытается это делать.Это, конечно, вопрос реализации, а не самого языка. Большей устойчивости можно добиться и без объекта, а за счет запрета на исполнение в адресных промежутках, в которых располагался текст модуля, после его выгрузки. Если, конечно, платформа предусматривает такие средства. в мак-версии бб указатели на процедуру косвенные. а когда модуль выгружается - они подменяются на код для трапа "nil procedure dereference". причем эта фича кажется вообще не зависит от бэкэнда компилятора. надо только включать режим pVarInd в DevCPE и подменять указатели в Kernel.UnloadMod. так что можно вообще ничего не выдумывать. |
Автор: | adimetrius [ Вторник, 03 Январь, 2023 14:08 ] |
Заголовок сообщения: | Re: Процедурные типы |
Я недавно сделал себе ProtectedUnload, которая "зачищает" таблицы типовых процедур в дескрипторах типов - точнее, заносит адрес процедуры, вызывающей авост. Это для меня полезно, поскольку я делаю модули с видами; при перезагрузке модуля, если где-то остался в окнах его вид, поведение - зависание, падение всего ББ, при первом же вызове Restore. Теперь, при ProtectedUnload, нет зависаний и падений ББ, а возникает обычный авост, потом можно окно с устаревшим видом закрыть, а иногда - просто удалить вид из его контейнера. Любопытно, если комплиятор может стоить таблицы процедур на i386 и делать косвенные вызовы. Вопрос, однако, в процедурных переменных: там что же, двойная косвенность - ссылка на таблицу, а оттуда - на процедуру? |
Страница 2 из 2 | Часовой пояс: UTC + 3 часа |
Powered by phpBB® Forum Software © phpBB Group https://www.phpbb.com/ |