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

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

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

EDIT

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

Пример:

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

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

Ответы [ 9 ]

19 голосов
/ 26 января 2010

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

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

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

Примеры:

  • Язык программирования 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 добавлена ​​опция для сборки мусора.)

В итоге:

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

  • Скомпилировано и интерпретировано как реализация .

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

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

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


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

4 голосов
/ 26 января 2010

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

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

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

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

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

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

4 голосов
/ 25 января 2010

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

2 голосов
/ 25 января 2010

Доступно несколько интерпретаторов C / C ++, например, этот .

Сам не пробовал, но, думаю, поскольку он заявляет, что он совместим с скомпилированным C / C ++, ему необходимо «ручное» управление памятью.

2 голосов
/ 25 января 2010

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

1 голос
/ 25 января 2010

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

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

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

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

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

1 голос
/ 25 января 2010

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

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 на ноль, что если вы установите его на c? b также будет c?

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

0 голосов
/ 25 января 2010

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

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

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

0 голосов
/ 25 января 2010

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

...