Исключение нулевого указателя генерируется, когда приложение пытается использовать null в случае, когда требуется объект. К ним относятся:
null
. null
. null
, как если бы это был массив. null
, как если бы это был массив. null
как будто это было значение Throwable. Приложения должны бросать экземпляры этого класса, чтобы указать на другие незаконные использования объекта null
.
Ссылка: http://docs.oracle.com/javase/8/docs/api/java/lang/NullPointerException.html
Я не забываю читать статью, которая может помочь Вам: Чейни на M.T.A. :-)
Некоторые реализации Схемы, которую я знаю, такой как SISC, выделяют свои кадры вызова на "куче".
@ollie: Вы не должны делать подъема, если все Ваши кадры вызова находятся на "куче". Существует компромисс в производительности, конечно: время для подъема, по сравнению с издержками, требуемыми выделить все кадры на "куче". Возможно, это должен быть настраиваемый параметр периода выполнения в интерпретаторе.:-P
Хорошая сводка доступна в Стратегии реализации Первоклассных Продолжений , статья Clinger, Hartheimer и Ost. Я рекомендую смотреть на реализацию Схемы Chez в частности.
Стек, копирующий, не то, что комплекс и существует много хорошо понятых методов, доступных для улучшения производительности. Используя выделенные "куче" кадры также довольно просто, но Вы делаете компромисс из создания наверху для "нормальной" ситуации, где Вы не используете явные продолжения.
при преобразовании входного кода в стиль передачи продолжения (CPS) тогда можно сойти с рук устранение стека в целом. Однако, в то время как CPS изящен, он добавляет другой шаг обработки во фронтэнде и требует, чтобы дополнительная оптимизация преодолела определенные последствия производительности.
Если Вы запускаете с нуля, действительно необходимо заглянуть к преобразованию Стиля передачи продолжения (CPS).
Хорошие источники включают "LISP в маленькие части" и Схема Marc Feeley в представлении 90 минут .
Примеры, на которые можно посмотреть: Курица (реализация Схемы, записанная в C та поддержка продолжения); Paul Graham На Lisp - где он создает преобразователь CPS для реализации подмножества продолжений в языке Common LISP; и Weblocks - основанная на продолжении веб-платформа, которая также реализует ограниченную форму продолжений в языке Common LISP.
Традиционный путь состоит в том, чтобы использовать setjmp
и longjmp
, хотя существуют протесты.
Patrick корректен, единственный способ, которым можно действительно сделать, это должно использовать явный стек в интерпретаторе и поднять соответствующий сегмент стека в "кучу", когда необходимо преобразовать в продолжение.
Это - в основном то же как, что необходимо для поддержки закрытий на языках, которые поддерживают их (закрытия и несколько связываемые продолжения).
Продолжение не является проблемой: вы можете реализовать его с помощью обычных функций высшего порядка с помощью CPS. Проблема с наивным распределением стека заключается в том, что хвостовые вызовы никогда не оптимизируются, а это означает, что вы не можете быть схемой.
Наилучший текущий подход к отображению стека спагетти схемы в стек - использование трамплинов: по сути, дополнительная инфраструктура для обработки не-C -как звонки и выходы из процедур. См. Батутный стиль (ps) .
Есть код , иллюстрирующий обе эти идеи.
Продолжения в основном состоят из сохраненного состояния стека и регистров ЦПУ в точке переключения контекста. По крайней мере, при переключении нет необходимости копировать весь стек в кучу, можно только перенаправлять указатель стека.
Прерывания тривиально реализуются с помощью волокон. http://en.wikipedia.org/wiki/Fiber_%28computer_science%29 . Единственное, что требует тщательной инкапсуляции, это передача и возврат значений параметров.
В Windows оптоволокно выполняется с помощью семейства вызовов CreateFiber/SwitchToFiber. В Posix-совместимых системах это можно сделать с помощью makecontext/swapcontext.
boost::coroutine имеет рабочую реализацию coroutines для C++, которая может служить ориентиром для реализации.
.Помимо хороших ответов, которые вы уже получили, я рекомендую книгу Эндрю Аппеля Compiling with Continuations. Она очень хорошо написана и, хотя не имеет прямого отношения к C, является источником действительно хороших идей для авторов компиляторов.
В Chicken Wiki также есть страницы, которые вы найдете очень интересными, например, внутренняя структура и процесс компиляции (где CPS объясняется на реальном примере компиляции).