Нулевой указатель

редактировать

В вычислении, указатель NULL или пустая ссылка является сохраненным значением для указания, что указатель или ссылка не относится к действительному объекту. Программы обычно используют нулевые указатели для представления таких условий, как конец списка неизвестной длины или невозможность выполнить какое-либо действие; это использование нулевых указателей можно сравнить с типами, допускающими значение NULL, и со значением Nothing в типе параметра.

Нулевой указатель не следует путать с неинициализированным указателем : нулевой указатель гарантированно не равен любому указателю, указывающему на действительный объект. Однако, в зависимости от языка и реализации, неинициализированный указатель может не иметь такой гарантии. Он может сравниваться с другими действительными указателями; или он может сравнивать равные нулевые указатели. И то и другое могло происходить в разное время; или сравнение может быть неопределенным.

СОДЕРЖАНИЕ
  • 1 К
  • 2 C ++
  • 3 Другие языки
  • 4 Нулевое разыменование
  • 5 Смягчение
  • 6 История
  • 7 См. Также
  • 8 ссылки
    • 8.1 Цитаты
    • 8.2 Источники
C

В C два нулевых указателя любого типа гарантированно сравниваются как равные. Макрос препроцессора NULLопределяется как определяемая реализацией константа нулевого указателя, которая в C99 может быть переносимо выражена как ((void *)0)означающая, что целочисленное значение 0преобразовано в тип void*(указатель на void ). Стандарт C не говорит, что нулевой указатель совпадает с указателем на адрес памяти  0, хотя на практике это может иметь место. Разыменование нулевого указателя является неопределенным поведением в C, и соответствующая реализация может предполагать, что любой указатель, для которого разыменован, не является нулевым.

На практике разыменование нулевого указателя может привести к попытке чтения или записи из памяти, которая не отображается, вызывая ошибку сегментации или нарушение доступа к памяти. Это может проявляться как сбой программы или трансформироваться в исключение программного обеспечения, которое может быть обнаружено программным кодом. Однако есть определенные обстоятельства, когда это не так. Например, в реальном режиме x86 адрес доступен для чтения и обычно для записи, и разыменование указателя на этот адрес является вполне допустимым, но обычно нежелательным действием, которое может привести к неопределенному, но не вызывающему сбоев поведению приложения. Бывают случаи, когда разыменование указателя на нулевой адрес является преднамеренным и четко определенным; например, код BIOS, написанный на C для 16-битных устройств x86 реального режима, может записывать IDT по физическому адресу 0 машины путем разыменования нулевого указателя для записи. Компилятор также может оптимизировать разыменование нулевого указателя, избегая ошибки сегментации, но вызывая другое нежелательное поведение. 0000:0000

C ++

В C ++, хотя NULLмакрос был унаследован от C, целочисленный литерал для нуля традиционно предпочитался представлять константу нулевого указателя. Однако в C ++ 11 nullptr вместо нее используется явная константа нулевого указателя.

Другие языки

В некоторых средах языков программирования (по крайней мере, в одной проприетарной реализации Lisp, например) значение, используемое в качестве нулевого указателя (вызываемого nilв Lisp ), может фактически быть указателем на блок внутренних данных, полезных для реализации (но не доступный явно из пользовательские программы), что позволяет использовать один и тот же регистр в качестве полезной константы и быстрого доступа к внутренним компонентам реализации. Это известно как nilвектор.

В языках с тегированной архитектурой возможно нулевой указатель может быть заменен тегированным объединением, которое обеспечивает явную обработку исключительного случая; фактически, возможно, нулевой указатель можно рассматривать как помеченный указатель с вычисляемым тегом.

В языках программирования для нулевого указателя используются разные литералы. В Python, например, вызывается нулевое значение None. В Pascal и Swift вызывается нулевой указатель nil. В Eiffel это называется voidссылкой.

Нулевое разыменование

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

  • В C разыменование нулевого указателя является неопределенным поведением. Многие реализации приводят к тому, что такой код приводит к остановке программы с нарушением доступа, потому что представление нулевого указателя выбирается как адрес, который никогда не выделяется системой для хранения объектов. Однако такое поведение не универсально. Это также не гарантируется, поскольку компиляторам разрешено оптимизировать программы в предположении, что они свободны от неопределенного поведения.
  • В Delphi и многих других реализациях Паскаля константа nilпредставляет собой нулевой указатель на первый адрес в памяти, который также используется для инициализации управляемых переменных. Разыменование его вызывает внешнее исключение ОС, которое отображается на экземпляр исключения Pascal EAccessViolation, если модуль System.SysUtils связан в предложении uses.
  • В Java доступ к нулевой ссылке запускает NullPointerException (NPE), который может быть обнаружен кодом обработки ошибок, но предпочтительной практикой является обеспечение того, чтобы такие исключения никогда не возникали.
  • В .NET доступ к нулевой ссылке вызывает исключение NullReferenceException. Хотя их перехват обычно считается плохой практикой, этот тип исключения может быть перехвачен и обработан программой.
  • В Objective-C сообщения могут быть отправлены nilобъекту (который является нулевым указателем), не вызывая прерывания программы; сообщение просто игнорируется, а возвращаемое значение (если есть) - nilили 0, в зависимости от типа.
  • До появления SMAP ошибка разыменования нулевого указателя могла быть использована путем сопоставления нуля страницы с адресным пространством злоумышленника и, следовательно, заставления нулевого указателя указывать на эту область. В некоторых случаях это могло привести к выполнению кода.
Смягчение

Существуют методы, облегчающие отладку разыменования нулевого указателя. Бонд и др. предлагаем изменить JVM, чтобы отслеживать нулевое распространение. Идея системы Casper заключается в использовании преобразования исходного кода для отслеживания этого распространения без изменения JVM. В некоторых случаях можно автоматически сгенерировать патч для исправления исключений с нулевым указателем.

История

В 2009 году сэр Тони Хоара заявил, что он изобрел ссылку нулевой в 1965 году как часть Алгол W языка. В этой ссылке 2009 года Хоар описывает свое изобретение как «ошибку на миллиард долларов»:

Я называю это своей ошибкой на миллиард долларов. Это было изобретение нулевой ссылки в 1965 году. В то время я проектировал первую всеобъемлющую систему типов для ссылок на объектно-ориентированном языке (АЛГОЛ W). Моя цель состояла в том, чтобы гарантировать, что любое использование ссылок должно быть абсолютно безопасным, с автоматической проверкой компилятором. Но я не мог устоять перед соблазном вставить пустую ссылку просто потому, что это было так легко реализовать. Это привело к бесчисленным ошибкам, уязвимостям и системным сбоям, которые, вероятно, причинили боль и ущерб на миллиард долларов за последние сорок лет.

Смотрите также
использованная литература

Цитаты

Источники

  • Объединенный технический комитет ISO / IEC JTC 1, Подкомитет SC 22, Рабочая группа WG 14 (2007-09-08). Международный стандарт ISO / IEC 9899 (PDF) (проект комитета).CS1 maint: несколько имен: список авторов ( ссылка )
Последняя правка сделана 2023-08-08 09:02:54
Содержание доступно по лицензии CC BY-SA 3.0 (если не указано иное).
Обратная связь: support@alphapedia.ru
Соглашение
О проекте