Oberon space
General Category => Общий раздел => Тема начата: valexey от Август 09, 2012, 01:05:21 pm
-
У Си (не С++) есть очень приятная особенность: если ты видишь что в юните нет инклюда #include <stdlib.h>, то и память там никто в куче (скорее всего! ибо манипуляция адресами как хочешь не запрещена) не выделяет.
В Обероне же когда смотришь на модуль не ясно использует он динамическую память (NEW) или же нет. А это иногда бывает важно. Например пишешь ты некий сервер, причем пишешь так, чтобы он работал гарантированно без сборщика мусора (и сборщик мусора для этого отключаешь возможно даже) - все либо на стеке, либо глобально. И используешь стороннюю либу, которой из самых общих соображений нет причин использовать динамическую память. А тут бац, в одном модуле внезапно кто-то использует. И все. Либо тормоза, либо память кончится.
Или же скажем программирование под мелкоконтроллеры - памяти там скажем 512 Байт (а может быть конечно и 8 Кб). Ясно что динамическая память и тем более сборщик мусора там противопоказан. Но, тем не менее, иногда хочется повторно использовать там хорошо зарекомендовавшие себя модули с больших систем. И неплохо бы изначально убедиться что они не используют динамическую память.
Я тут вижу три варианта решения проблемы:
1) Модификация языка, такая, что для использования NEW было необходимо скажем импортировать модуль MemManager.
2) Решение на уровне компилятора - при специальном ключике компилятора он отрубит сборщик мусора и динамическую память вообще, и на NEW будет ругаться плохими словами.
3) Сторонняя тулза которая прошерстит исходники даденых модулей и скажет если вдруг кто-то динамической памятью там пользуется (хм. можно просто сделать grep * NEW).
При выборе варианта, видимо, не следует смотреть на обратную совместимость с существующими компиляторами и исходниками на Обероне.
-
3) Сторонняя тулза которая прошерстит исходники даденых модулей и скажет если вдруг кто-то динамической памятью там пользуется (хм. можно просто сделать grep * NEW).
Вероятно, это проще всего, и поэтому никто и не делает пункты 1 и 2...
-
3) Сторонняя тулза которая прошерстит исходники даденых модулей и скажет если вдруг кто-то динамической памятью там пользуется (хм. можно просто сделать grep * NEW).
Лично я именно про это и подумал сразу - grep и все дела. Просто и надежно. Список всех модулей для "проверяемого" проекта все равно обязан быть на руках.
P.S. А кто мешает в C (не С++) сделать malloc без #include? ;)
-
Изменять язык не нужно, достаточно модифицировать компилятор. NEW это встроенная процедура и привязать её к какому-нибудь псевдомодулю - несколько строк кода.
Вместо ключей лучше прагму, чтобы видно было.
Либо, если я правильно понял, тебе надо что-то вроде спецификации модуля, что решит и ряд других проблем
-
P.S. А кто мешает в C (не С++) сделать malloc без #include? ;)
Стандарт C99. (не говоря уже о C12)
-
Либо, если я правильно понял, тебе надо что-то вроде спецификации модуля, что решит и ряд других проблем
Спецификация модуля (явная) это то, чего мне реально не хватает во всех этих новомодных языках, начиная от оберона и жабы и кончая Rust, Go, D.
-
Либо можно сделать как в Сириусе.
У нас псевдомодуль SYSTEM оставлен для совместимости, а вместо него используются модификаторы модуля
MODULE [UNSAFE, HOST, CPU, BOARD, TARGET...] Name;
Так же можно сделать и MODULE [STATIC]... и всё
-
Либо можно сделать как в Сириусе.
У нас псевдомодуль SYSTEM оставлен для совместимости, а вместо него используются модификаторы модуля
MODULE [UNSAFE, HOST, CPU, BOARD, TARGET...] Name;
Так же можно сделать и MODULE [STATIC]... и всё
То есть, по сути, атрибуты модуля? Его свойства. Да, идея хороша.
-
Да, хотя эти атрибуты придется хранить в символьных/объектных файлах со всеми вытекающими по модификации
-
Да, хотя эти атрибуты придется хранить в символьных/объектных файлах со всеми вытекающими по модификации
А зачем? В том смысле, зачем эта информация в рантайме вообще? Ну и как атрибуты одного модуля могут влиять на процесс компиляции другого модуля?
-
ну как же, если у нас все модули одна статика, и статически слинкованы, то зачем нам вообще грузить/линковать модуль управления памятью
-
ну как же, если у нас все модули одна статика, и статически слинкованы, то зачем нам вообще грузить/линковать модуль управления памятью
Давай не будем путать статическую и автоматическую память (а также динамическую память) со статической/динамическом компоновкой/линковкой. (я не к тому что ты путаешь, просто у тебя в предложении как-то это смешалось все, народ может войти в заблужденье)
Ясное дело что в объектнике (или sym-файле, не важно) должны быть указание на то, какие функции/процедуры оно использует и из какого модуля. Естественно если оно использует NEW, то это там должно быть прописано. И если при статической компоновке мы (компоновщик ака линкер) видим что кто-то этот NEW использует, то нужно достать из загашника модуль менеджера динамической памяти и включить его в сборку (если только нам это явным образом программер не запретил, если запретил, то ошибку нарисовать).
В случае же динамической загрузки может быть вообще все веселее - подгружать менеджер памяти можно не тогда когда загружается модуль, а когда кто-то первый раз пытается использовать NEW. В этом случае этот NEW в sym/obj может не светиться вообще.
PS. Вообще, на современном этапе развития девелоперского железа я не вижу проблемы в скорости сборки исходников на Обероне.
-
дак я то же самое сказал )))
но да, у меня есть такая проблема - очевидные для меня вещи я опускаю, в результате возникает недопонимание, потому как иногда это приводит к двусмысленности
-
А тут бац, в одном модуле внезапно кто-то использует. И все. Либо тормоза, либо память кончится.
Зацени размеры бедствия. В дотнете при преобразовании структуры System.DateTime из UTC в локальное время в динамической памяти создаётся мусор в виде boxed объекта System.Int32. При преобразовании структуры System.Guid в System.String тоже генерируется какой-то мусор уже не помню какой. При использовании foreach по коллекции из System.Object или по рукописной коллекции в куче генерируется мусор в виде объекта иттератора (хотя foreach по встроенным generic коллекциям (System.Collections.Generic.*) мусора не генерит). При вызове процедуры с переменным количеством аргументов генерируется мусор в виде массива этих аргументов. В частности, при конкатенации более трёх строк "aaa" + s1 + "bbb" + s2 неявно вызывается процедура с переменным количеством аргументов, то есть создаётся мусорный массив из строк. Ну и тому подобное ещё вагон и маленькая тележка...
-
А тут бац, в одном модуле внезапно кто-то использует. И все. Либо тормоза, либо память кончится.
Зацени размеры бедствия. В дотнете при преобразовании структуры System.DateTime из UTC в локальное время в динамической памяти создаётся мусор в виде boxed объекта System.Int32. При преобразовании структуры System.Guid в System.String тоже генерируется какой-то мусор уже не помню какой. При использовании foreach по коллекции из System.Object или по рукописной коллекции в куче генерируется мусор в виде объекта иттератора (хотя foreach по встроенным generic коллекциям (System.Collections.Generic.*) мусора не генерит). При вызове процедуры с переменным количеством аргументов генерируется мусор в виде массива этих аргументов. В частности, при конкатенации более трёх строк "aaa" + s1 + "bbb" + s2 неявно вызывается процедура с переменным количеством аргументов, то есть создаётся мусорный массив из строк. Ну и тому подобное ещё вагон и маленькая тележка...
Угу. В java нечто аналогичное происходит. Но все это компенсируется поколенным сборщиком, то есть это неэффективность в малом, оно не расползается на большое. Впрочем, если вдруг в какой-нибудь mono тупой консервативный (или даже точный, но без поколений) сборщик мусора, то ой.
В хаскеле, кстати, по крайней мере для некого небольшого объема новейших данных (мегабайт что-ли) используется копирующий сборщик, который работает тем быстрее чем больше в этом самом мегабайте мусора :-) То есть промежуточный мусор это не есть большая проблема если вся система (не ОС, а комплекс из рантайма, компилятора и так далее) на это заточена. В случае Оберонов никто под это дело затачивать систему не собирается. Поэтому там имеет смысл пойти по другому пути :-)
-
Впрочем, если вдруг в какой-нибудь mono тупой консервативный (или даже точный, но без поколений) сборщик мусора, то ой.
Это, кстати, отсекает наивные (простые) реализации .net/c#, java и так далее. Они дефакто не конкурентноспособны, просто из за того что будут вот подобные вот проблемы. Повышается порог вхождения для новых реализаций .net/java/haskell. Уменьшается конкуренция и имеем больше vendor lock in. В общем, это не слишком здорово, да. Хотя иногда вполне терпимо.
-
И неплохо бы изначально убедиться что они не используют динамическую память.
Сам по себе NEW не шибко вреден, вред причиняет слишком частый его вызов и слишком большое количество динамических объектов, а это автоматической тулзовиной из исходников не вытянешь, самому врубаться надо.
-
3) Сторонняя тулза которая прошерстит исходники даденых модулей и скажет если вдруг кто-то динамической памятью там пользуется (хм. можно просто сделать grep * NEW).
Лично я именно про это и подумал сразу - grep и все дела. Просто и надежно. Список всех модулей для "проверяемого" проекта все равно обязан быть на руках.
Кстати, grep не поможет если у нас используются сторонние проприентарные либы (ака пачки модулей). То есть сторонние модули в виде бинарей. Конкретная реализация оберона может вместо вызова функции NEW делать инлайн оной функции и grep ничего не даст.
Таким образом на уровне языка все же нужны изменения. Вариант от Kemet'a мне понравился.
-
И неплохо бы изначально убедиться что они не используют динамическую память.
Сам по себе NEW не шибко вреден, вред причиняет слишком частый его вызов и слишком большое количество динамических объектов, а это автоматической тулзовиной из исходников не вытянешь, самому врубаться надо.
Зависит от сценария и окружения. Если у тебя памяти всего порядка единиц килобайт и есть требования к реалтайму (не софт реалтайм, как в телекоме, а настоящий реалтайм - если не уложился во время переферийное устройство просто зависнет нафик, потребудется перезагрузка), то сборщик мусора становится категорически противопоказан в любых колличествах. Это с одной стороны.
С другой также противопоказано с нуля рисовать все модули и собирать велосипеды, потому что времени, как обычно, не хватает, и при написании всех базовых модулей с нуля будет далеко не ноль ошибок. Поэтому неплохо бы иметь способ определения какие модули годятся для переноса в такую специфическую среду, а какие нет/надо переделывать. Хотя, тут наверно действительно помог бы grep - ведь такие модули у нас всяко есть в исходниках.
-
чем больше читаю постов в этой теме, тем более укрепляется ощущение что в этой области публике больше прокатит упрощенный СИ...
-
Не хотите сборщика мусора? Берите Модулу-2.
-
Не хотите сборщика мусора? Берите Модулу-2.
Зачем же сразу Модулу-2? В описании Оберона (тех самых 16 страницах) ничего же не говорится про сборщик мусора, GC является обязательным лишь для Компонентного Паскаля...
-
Не хотите сборщика мусора? Берите Модулу-2.
Зачем же сразу Модулу-2? В описании Оберона (тех самых 16 страницах) ничего же не говорится про сборщик мусора, GC является обязательным лишь для Компонентного Паскаля...
Начиная как минимум с Оберона-2. Возможно даже еще в Object Oberon'e. См. дерево: http://www.oberon.ethz.ch/language/genealogy/ Отлично видно, что Oberon, Oberon-07/12 принадлежат к другой ветке.
-
Не хотите сборщика мусора? Берите Модулу-2.
Зачем же сразу Модулу-2? В описании Оберона (тех самых 16 страницах) ничего же не говорится про сборщик мусора, GC является обязательным лишь для Компонентного Паскаля...
А каким образом освобождать выделенную динамическую память?
-
Не хотите сборщика мусора? Берите Модулу-2.
Зачем же сразу Модулу-2? В описании Оберона (тех самых 16 страницах) ничего же не говорится про сборщик мусора, GC является обязательным лишь для Компонентного Паскаля...
А каким образом освобождать выделенную динамическую память?
Это уже детали реализации.
-
Не хотите сборщика мусора? Берите Модулу-2.
Зачем же сразу Модулу-2? В описании Оберона (тех самых 16 страницах) ничего же не говорится про сборщик мусора, GC является обязательным лишь для Компонентного Паскаля...
А каким образом освобождать выделенную динамическую память?
Это уже детали реализации.
Мне известно о двух видах работы с памятью: ручного (программистом) и автоматического сбора памяти (сборщиком мусора). Если для ручного сбора выделенной памяти отсутствует операция для освобождения памяти, то следует подразумевать, что она будет освобождена автоматически, без явного указания.
Какой разработчик компилятора Оберона с ручным управлением памяти допустит использование процедуры NEW без соответствующей ей пары в виде DISPOSE?
Или, по-твоему, в таком компиляторе будет использоваться дополнительный модуль для ручного сбора памяти (наподобие MemMgr.DISPOSE)? :)
-
Это уже детали реализации.
Мне известно о двух видах работы с памятью: ручного (программистом) и автоматического сбора памяти (сборщиком мусора). Если для ручного сбора выделенной памяти отсутствует операция для освобождения памяти, то следует подразумевать, что она будет освобождена автоматически, без явного указания.
Какой разработчик компилятора Оберона с ручным управлением памяти допустит использование процедуры NEW без соответствующей ей пары в виде DISPOSE?
Или, по-твоему, в таком компиляторе будет использоваться дополнительный модуль для ручного сбора памяти (наподобие MemMgr.DISPOSE)? :)
Например DISPOSE можно запихать в какой-нибудь псевдомодуль, например SYSTEM. Ну а на крайняк, почему бы и не в отдельный настоящий модуль вроде MemMgr?
-
Ну если тебе так больше нравится, то уж лучше сразу NEW и DISPOSE отделить от языка.
-
Кстати, в спецификации О-2 от Вирта явно определена нужность сбора мусора и основы его реализации (пп. D3,5).
-
Кстати, в спецификации О-2 от Вирта явно определена нужность сбора мусора и основы его реализации (пп. D3,5).
Oberon-2 не совсем от Вирта все же. И да, про этом в этом топике уже упоминалось:
Не хотите сборщика мусора? Берите Модулу-2.
Зачем же сразу Модулу-2? В описании Оберона (тех самых 16 страницах) ничего же не говорится про сборщик мусора, GC является обязательным лишь для Компонентного Паскаля...
Начиная как минимум с Оберона-2. Возможно даже еще в Object Oberon'e. См. дерево: http://www.oberon.ethz.ch/language/genealogy/ Отлично видно, что Oberon, Oberon-07/12 принадлежат к другой ветке.
-
Псевдомодуль GC добавляет предопределённую процедуру NEW, а псевдомодуль DM добавляет процедуры NEW и DROP. Модули взаимоисключаемые, и за этим может следить компилятор.
-
Ну если тебе так больше нравится, то уж лучше сразу NEW и DISPOSE отделить от языка.
Я слабо представляю как можно NEW отделить от языка - это не типичная процедура и/или функция. Средствами языка нельзя реализовать процедуру NEW.
-
Кстати, в спецификации О-2 от Вирта явно определена нужность сбора мусора и основы его реализации (пп. D3,5).
Oberon-2 не совсем от Вирта все же. И да, про этом в этом топике уже упоминалось:
...
Да, точно... :) Сборку мусора для Оберона он описывает в "Проекте Оберон", и это ессно не описание языка... :)
-
Ну если тебе так больше нравится, то уж лучше сразу NEW и DISPOSE отделить от языка.
Я слабо представляю как можно NEW отделить от языка - это не типичная процедура и/или функция. Средствами языка нельзя реализовать процедуру NEW.
И что ? можно рассматривать Оберон без GC(и динамически распределяемой памятью) как подмножество Оберона с GC(как это делают в Австралии) - хотя правомерно ли называть Обероном это подмножество..вопрос еще тот, поэтому не проще ли будет повысить СИ , или понизить С++
-
Мне известно о двух видах работы с памятью: ручного (программистом) и автоматического сбора памяти (сборщиком мусора).
Ну есть ещё как минимум третий: http://en.wikipedia.org/wiki/Region-based_memory_management
-
Всё же чутьё подсказывает, что таки проще изменить Оберон нежели Си.
А как называть - не вопрос. Называйте хоть Абероном. "А" - альтернативный. Прям как форум. :)
P.S.
Кстати, "DROP" не надо. Сильно ассоциируется с SQL.
-
А чем он идеологически отличается от ручного управления?
пара
createRegion()
destroyRegion()
присутствует...
-
Всё же чутьё подсказывает, что таки проще изменить Оберон нежели Си.
А как называть - не вопрос. Называйте хоть Абероном. "А" - альтернативный. Прям как форум. :)
P.S.
Кстати, "DROP" не надо. Сильно ассоциируется с SQL.
Hello, my name is "Robert'); DROP TABLE Students; --"
:-)
-
Всё же чутьё подсказывает, что таки проще изменить Оберон нежели Си.
А как называть - не вопрос. Называйте хоть Абероном. "А" - альтернативный. Прям как форум. :)
P.S.
Кстати, "DROP" не надо. Сильно ассоциируется с SQL.
:D Ох не уверен, что сама идея модульности хороша для подобных систем. Насчет "Аберона"... ;D не заговаривайтесь у меня фантазия очень богатая (давненько в коровне я назвал это дело Обсероном -Ильина аж скукожило (судя по личному сообщению) ;D - а здесь ведь эцилопов нет... так что надо с пониманием относится к чувствам верующих).
-
... точнее динамической компоновки модулей.
-
Hello, my name is "Robert'); DROP TABLE Students; --"
:-)
ненене, вот как там было: :D
(http://media.smashingmagazine.com/cdn_smash/wp-content/uploads/2010/10/sql.png)
-
А чем он идеологически отличается от ручного управления?
пара
createRegion()
destroyRegion()
присутствует...
Да, немного неудачный пример я привёл.
Ну, во-первых, в языках типа C# можно автоматизировать вызов процедуры destroyRegion(), если оформить это в конструкцию using:
using (Region r = new Region())
{
// Здесь используем этот регион
Object o = r.New<Object>();
...
}
// А здесь компилятор вставляет вызов уничтожения региона
В языках без конструкции using (типа оберона) или без возможности создать аналог using самостоятельно (а это легко можно сделать в тех же лиспе, смоллтоке или хаскелле -- в языках с замыканиями), там да, придётся вручную освобождать регионы...
Во-вторых, ведутся работы по автоматическому управлению регионами. Хотя это, наверное, уже вариация на тему GC...
-
Во-вторых, ведутся работы по автоматическому управлению регионами. Хотя это, наверное, уже вариация на тему GC...
Второй наводящий вопрос - в чем принципиально отличается "автоматическое управление регионами", от автоматического управления загрузкой\выгрузкой модулей (в том смысле как они понимаются в Обероне), и в свою очередь от GC? Ох а как вспомнишь, что Обероны в принципе допускают кроссмодульную неявную рекурсию.....
-
Ну, во-первых, в языках типа C# можно автоматизировать вызов процедуры destroyRegion(), если
...
В языках без конструкции using (типа оберона) или без возможности создать аналог using самостоятельно (а это легко можно сделать в тех же лиспе, смоллтоке или хаскелле -- в языках с замыканиями), там да, придётся вручную освобождать регионы...
Ну, то есть это обычный RAII/умные указатели в С++ :-)
-
Во-вторых, ведутся работы по автоматическому управлению регионами. Хотя это, наверное, уже вариация на тему GC...
Второй наводящий вопрос - в чем принципиально отличается "автоматическое управление регионами", от автоматического управления загрузкой\выгрузкой модулей (в том смысле как они понимаются в Обероне), и в свою очередь от GC? Ох а как вспомнишь, что Обероны в принципе допускают кроссмодульную неявную рекурсию.....
Автоматическое управление загрузкой и выгрузкой модулей в обероне? Не, не слышал.
В блекбоксе, по крайней мере, модули надо выгружать вручную.
Отличие же от GC не только в том, что память освобождается разом для всех объектов, созданных в ней.
Обычно GC собирает мусор, когда при очередном запросе на выделение памяти под объект обнаруживается потенциальный дефицит памяти в ближайшем будущем.
Автоматическое освобождение региона вообще никак не связано с запросами на создание нового объекта. Компилятор, проанализировав текст программы, определяет, где нужно освободить регион, то есть освобождение памяти в регионе является статическим, а не динамическим как у GC.
Это похоже на распределение переменных в стеке -- при вызове подпрограммы в стеке выделяется память под её локальные переменные, при завершении подпрограммы эта память автоматически освобождается. Никакой сборщик мусора тут не нужен...
-
Отличие же от GC не только в том, что память освобождается разом для всех объектов, созданных в ней.
Обычно GC собирает мусор, когда при очередном запросе на выделение памяти под объект обнаруживается потенциальный дефицит памяти в ближайшем будущем.
Автоматическое освобождение региона вообще никак не связано с запросами на создание нового объекта.
Можно сократить объяснение: GC-ленивый (ленивые вычисления, да), а регионы энергичны.
-
Автоматическое освобождение региона вообще никак не связано с запросами на создание нового объекта. Компилятор, проанализировав текст программы, определяет, где нужно освободить регион, то есть освобождение памяти в регионе является статическим, а не динамическим как у GC.
Это похоже на распределение переменных в стеке -- при вызове подпрограммы в стеке выделяется память под её локальные переменные, при завершении подпрограммы эта память автоматически освобождается. Никакой сборщик мусора тут не нужен...
Каким образом это возможно если скажем создание региона поместить в ветку условного оператора выполняющуюся в зависимости от динамического условия?
-
Каким образом это возможно если скажем создание региона поместить в ветку условного оператора выполняющуюся в зависимости от динамического условия?
А в чём проблема? Этот регион явно завершит своё существование, когда закончится тело той ветки IF, в которой он был создан...
-
наверное в том, что он может вообще не создаваться на практике...
-
наверное в том, что он может вообще не создаваться на практике...
Ну так тем более: нет региона -- нет проблемы!
-
наверное в том, что он может вообще не создаваться на практике...
Ну так тем более: нет региона -- нет проблемы!
:) точно МММ-нет проблем!
-
Кстати, по сути в erlang'e память тоже регионами управляется, а в рамках каждого региона имеется сборщик мусора :-)
-
Если серьёзно, то на использование регионов надо накладывать ограничение -- объекты, в нём созданные, могут быть присвоены лишь тем переменным, область и время жизни которых не больше, чем у этого региона. Если программист попытается присвоить этот объект переменной, глобальной для этого региона, он получит по рукам от компилятора.
В этом случае принятие решения о месте и времени уничтожения региона становится тривиальным...
-
Если серьёзно, то на использование регионов надо накладывать ограничение -- объекты, в нём созданные, могут быть присвоены лишь тем переменным, область и время жизни которых не больше, чем у этого региона. Если программист попытается присвоить этот объект переменной, глобальной для этого региона, он получит по рукам от компилятора.
В этом случае принятие решения о месте и времени уничтожения региона становится тривиальным...
некомильфо в общем случае, ограничение на использование динамической памяти коверкающее алгоритмику .
-
В Аде есть access types (что-то типа ссылочных типов), их можно представить как регионы -- когда действие программы выходит за область видимости таких типов, то все объекты этих типов тут же уничтожаются.
-
Я слабо представляю как можно NEW отделить от языка - это не типичная процедура и/или функция. Средствами языка нельзя реализовать процедуру NEW.
Кстати, в ББ можно описать её как PROCEDURE NEW (OUT p: SYSTEM.PTR). PTR-у можно присваивать любое указательное значение. Т.е. это нетипизированный GC-шный указатель. Недокументированная вещь. Просто для информации :)
-
Я слабо представляю как можно NEW отделить от языка - это не типичная процедура и/или функция. Средствами языка нельзя реализовать процедуру NEW.
Кстати, в ББ можно описать её как PROCEDURE NEW (OUT p: SYSTEM.PTR). PTR-у можно присваивать любое указательное значение. Т.е. это нетипизированный GC-шный указатель. Недокументированная вещь. Просто для информации :)
Объявить то можно, а вот реализовать уже нет. Но все равно спасибо.
-
В каком смысле нельзя реализовать? В ББ NEW заменяется на вызов Kernel.NewRec.
-
В каком смысле нельзя реализовать? В ББ NEW заменяется на вызов Kernel.NewRec.
В прямом. Возможно я чего-то не понимаю, но NEW кроме указателя по ссылке (то есть куда записать) нужно ведь знать и тип этого указателя (а по типу нужно иметь возможность узнать размер записи). Насколько я понимаю, указатели даже в ББ это не тэгированные типы, соответственно в рантайме информации о типе нет. Следовательно мы не знаем сколько памяти нужно выделять.
-
Да, всё верно, Алексей. Упустил.
Вот сделать процедуру, которая будет работать так:
VAR r: RECORD ptr: MyObject END;;
New(r)
- можно.
-
Да, всё верно, Алексей. Упустил.
Вот сделать процедуру, которая будет работать так:
VAR r: RECORD ptr: MyObject END;;
New(r)
- можно.
Только, насколько я понимаю тут опять же тип будет вытаскиваться в рантайме и размер тоже. Что не слишком эффективно (ну, то есть жаба душит делать в рантайме то, что гарантированно могло быть сделано в compile time). Впрочем, это уже мелочи :-)
В Обероне NEW штука волшебная. Самое забавное что NEW то процедура с возвратом значения через параметр, а вот NewRec в BB вполне себе функция, которая принимает тип и возвращает указатель: PROCEDURE NewRec* (typ: INTEGER): INTEGER; (кстати, а почему тут сэкономили одну букву - вместо type написали typ? в этом какое-то великий смысл?)
-
Не знаю, почему typ, принято так в ядре у них обозначать целочисленный код типа.