Интерпретированные языки с ручным управлением памятью?

Какие интерпретируемые языки не содержат указателей (IE: Python, Java, Perl, PHP, Ruby, Javascript и т.д.) имеют ручное управление памятью? Я не помню, чтобы когда-либо слышал об этом.

Не является ли серьезная проблема интерпретируемых языков недетерминированными задержками (или сложностью пространства, когда не хватает задержки) сбора мусора? Итак, почему бы просто не написать что-то точно, как Java, но заставляет вас освобождать память вручную?

ИЗМЕНИТЬ

Что я подразумеваю под управлением ручной памяти, так это то, что язык будет иметь ссылки на объекты, и вы можете удалить объект с помощью ссылки.

Пример:

Object a = new Object(); // a is a reference to the object
Object b = a; // b is a reference to the same object
a.method(); // fine
delete b; // delete the object referenced by b
a.method(); // null dereference exception

Итак, какие оговорки (кроме утечек памяти) могут присутствовать на языке, подобном этому примеру?

Ответ 1

Помещения, стоящие за вопросом, немного изворотливы:

  • Модель памяти является свойством языка, а не его реализацией.

  • интерпретируется как свойство реализации, а не язык.

Примеры:

  • Язык программирования Scheme имеет автоматическое управление памятью и имеет множество десятков интерпретируемых реализаций, но также некоторые мелкие компиляторы с собственным кодом, включая Larceny, Gambit и PLT Scheme (который включает в себя как интерпретатор, так и JIT-компилятор делая плавные переходы).

  • Язык программирования Haskell имеет автоматическое управление памятью; двумя наиболее известными реализациями являются интерпретатор HUGS и компилятор GHC. Существует несколько других почетных реализаций, разделенных равномерно между компиляцией на собственный код (yhc) и интерпретацией (Helium).

  • Язык программирования C имеет ручное управление памятью, и в то время как мир полон компиляторов C, те из нас, кто достаточно взрослый, чтобы помнить славные 1980-е годы, могут помнить Sabre-C или C-terp, два очень полезных переводчика C для MS-DOS.

Тем не менее, за вашим вопросом есть правдивое замечание: обычно скомпилированы языки с ручным управлением памятью. Почему?

  • Ручное управление памятью - это устаревшая функция, часто используемая для совместимости с устаревшим кодом. Устаревшие языки обычно достаточно зрелы, чтобы иметь компиляторы с собственным кодом.

  • Многие новые языки определяются реализацией. Проще построить интерпретатор, чем создавать компилятор. Легче реализовать простое автоматическое управление памятью в интерпретаторе, чем реализовать высокопроизводительное автоматическое управление памятью в компиляторе собственного кода. Поэтому, если язык получает свое определение от его первой реализации, автоматическое управление памятью коррелирует с интерпретацией, потому что в интерпретируемой настройке реализация проще.

  • Ручное управление памятью также (а иногда и оправданно) используется для повышения производительности. Бен Зорн, отличные экспериментальные исследования 1990-х годов, показывают, что автоматическое управление памятью так же быстро или быстро, как ручное управление памятью, но требует в два раза больше памяти. Поэтому ручное управление памятью часто используется на очень маленьких устройствах, где памяти мало, а в очень больших центрах обработки данных, где удвоение памяти дорого. (Он также иногда используется людьми, которые мало знают об управлении памятью, но слышали, что сбор мусора медленный. Они были правы в 1980 году.) И когда есть проблема с производительностью, вы обычно находите компилятор с собственным кодом, чем интерпретатор.

    Некоторые из действительно интересных исключений также вытекают из этого принципа. Например, как FORTH, так и самые первые реализации PostScript были разработаны для работы на небольших встроенных устройствах (телескопы и принтеры), где ресурсы памяти были недостаточными, но время вычисления не было фактором. Оба языка были впервые реализованы с использованием байт-кодов, которые были более компактными, чем собственный код, и оба предназначались для управления ручной памятью. Итак: переводчики с ручным управлением памятью. (Более поздние версии PostScript добавили опцию для сбора мусора.)

Вкратце:

  • Автоматическое и ручное управление памятью - это язык.

  • Скомпилированный vs интерпретируется как реализация.

  • В принципе два варианта могут быть и сделаны ортогонально, но по прагматичным причинам техники автоматическое управление памятью часто коррелирует с интерпретацией.

Не является ли серьезная проблема для интерпретируемых языков недетерминированными задержками (или сложностью пространства, когда не хватает задержки) сбора мусора?

Я не знал, что существует серьезная озабоченность в отношении интерпретируемых реализаций языков программирования. В алфавитном порядке Lua, Perl, PostScript, Python и Ruby все безумно успешны, а Icon, Scheme и Squeak Smalltalk умеренно успешны. Единственная область, в которой непредсказуемые задержки вызывают беспокойство, - это жесткие вычисления в реальном времени, такие как система ABS, которая управляет тормозами вашего автомобиля (если вы водите машину с достаточно фантазией).


Заметка добавлена ​​после редактирования вопроса:Вы изменили "интерпретируемый" на "без указателей". Но вы говорите в комментарии, что вы хотите спросить о языках с new и delete. Любой язык с new и delete имеет указатели: по определению, любой new возвращает указатель. (На некоторых языках могут быть и другие источники указателей.) Поэтому я думаю, что вы хотите сказать "языки без арифметики указателей и без адреса оператора".

Ответ 2

Forth имеет штабелированные области памяти, которые могут быть освобождены с помощью FORGET.

Ответ 3

Какие интерпретируемые языки имеют ручное управление памятью? Я не помню, чтобы когда-либо слышал об этом.

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

Является ли С компилируемым языком? Там есть переводчики С. Является ли Python интерпретированным языком? Все 8 текущих реализаций Python используют компилятор.

Итак, поскольку каждый язык может иметь интерпретированную реализацию, C и С++ являются примерами интерпретируемых языков с ручным управлением памятью. (И это не просто теоретический конкурс по расщеплению волос, на самом деле есть интерпретаторы C и С++. Операционная система VxWorks в реальном времени даже содержит одно прямое ядро, и NASA однажды использовало этот интерпретатор для исправления неисправного модуля ядра на космическом корабле.)

Другим примером может быть первая версия Lisp с 1958 года: у нее было ручное управление памятью (на основе подсчета ссылок), но она была заменена всего на пару месяцев версией с автоматическим управлением памятью, что с тех пор используется. Хотя, опять же, любой язык может быть реализован либо с помощью компилятора, либо с помощью интерпретатора, поэтому я не знаю, была ли эта версия интерпретированной или скомпилированной. (На самом деле, я не уверен, было ли это реализовано вообще.)

Если вы немного ослабляете свои критерии и понимаете, что управление памятью является лишь особым случаем общего управления ресурсами, то вы обнаружите, что почти все языки, независимо от того, хотите ли вы их компилировать или интерпретировать или что-то еще, имеют некоторую форму управления ресурсами вручную, по крайней мере для какого-то ресурса (файлы, соединения с базами данных, сетевые подключения, кеши,...).

Ответ 4

В некоторых высокопроизводительных интерпретируемых языках, таких как Lua, вы можете вручную обрабатывать сборку мусора. См. lua_gc.

Ответ 5

Существуют некоторые интерпретаторы C/С++, например этот.

Не пробовал самостоятельно, но я думаю, что, поскольку он утверждает, что совместим с компилируемым C/С++, он должен иметь "ручное" управление памятью.

Ответ 6

Причиной являются круговые ссылки, исключения нулевого указателя и множественные ссылки. Простой пример:

var a = new Object();
var b = a;
a = null;//or delete a or free a or whatever;
print(b);//what now? is b null? or is b still new Object()?

Если в приведенном выше примере b теперь является нулевым, в результате возникают переопределения переменных. Например, вместо установки a в значение null, что, если вы установите его на c? было бы b также c?

Вы можете прочитать о других проблемах, таких как круговые ссылки, на wikipedia.

Ответ 7

Итак, отвечая на эту часть вопроса:

Не главное беспокоиться о интерпретируемых языков недетерминированные задержки (или пространство сложность, когда этого недостаточно задержка) сбора мусора? Так почему не просто пишите что-то точно Java, но заставляет вас освобождать память вручную?

Это может быть проблемой для некоторых систем. Не проблема для других систем. Программное обеспечение, запущенное с сборкой мусора, может выделять память быстрее, чем системы, которые просто называют malloc. Конечно, вы в конечном итоге оплачиваете время позже в GC время.

Возьмите веб-систему, например. Вы можете выделить всю память во время обработки запроса, после чего GC может собираться. Возможно, это не закончится так, но вы получите эту идею.

Существует множество различных стратегий сбора мусора. Какая стратегия лучше всего подходит для системы, будет зависеть от требований. Но даже если вам нужен абсолютный детерминизм, вы можете использовать что-то вроде: Realtime Java

Ответ 8

Интерпретировано не обязательно означает сбор мусора. Perl, Tcl, Python и т.д. И т.д. Я считаю, что все используют простой подсчет ссылок, поэтому рекультивация памяти является детерминированной, хотя и не совсем прозрачной (когда-либо пробованной strace в программе Perl?).

Ответ 9

API Python официально разрешает включать или отключать отложенную сборку мусора - Проверьте документацию на модуле "gc" стандартной библиотеки:

http://docs.python.org/library/gc.html

Но это не то, что заставляет его замедляться по сравнению со статическими языками - динамическая природа самих данных является основной причиной различий в скорости.