Безопасность null-значений

Безопасность null-значений (англ. void safety или англ. null safety) — гарантированное свойство, реализуемое в объектно-ориентированных языках программирования с целью предотвращения наличия у ссылок на объекты нулевого указателя (или void).

В объектно-ориентированных языках доступ к объектам осуществляется через ссылки (или, эквивалентно, указатели). Типичный вызов имеет вид:

x.f(a, ...)

где f обозначает некоторую операцию, а x — ссылку на объект. Во время выполнения ссылка может оказаться void или null (в русской терминологии — нулевая ссылка). В этих случаях вызов превращается в пустой или null-вызов (англ. void call), что приводит к генерации исключения на этапе исполнения программы (run-time), зачастую вызывая аварийное завершение работы программы.

Безопасность null-значений обеспечивает (на этапе компиляции) гарантию того, что пустой или null-вызов никогда не произойдёт.

История

В выступлении 2009 года Тони Хоар назвал изобретение нулевого указателя своей самой дорогой ошибкой, допущенной при проектировании языка ALGOL W:

Считаю это своей миллиардной ошибкой. Это было изобретение null-ссылки в 1965 году. В то время я разрабатывал первую полную систему типов для ссылок в объектно-ориентированном языке программирования (ALGOL W). Моя цель заключалась в том, чтобы все использования ссылок были абсолютно безопасными с автоматической проверкой компилятором. Однако я не смог устоять перед искушением добавить null-указатель — просто потому, что реализовать это было крайне легко. В результате появились бесчисленные ошибки, уязвимости, сбои систем, что, возможно, причинило миллиарды долларов убытков и боли на протяжении последних 40 лет[1].

Бернар Мейер предложил сам термин «void safety»[2].

Реализация в языках программирования

Первые попытки гарантировать безопасность null-значений предпринимались при проектировании языка Self.

Язык Eiffel соответствует требованиям безопасности null-значений согласно своим стандартам ИСО и ECMA; механизм void safety реализован в EiffelStudio начиная с версии 6.1, с использованием современной синтаксической нотации — начиная с версии 6.4.

Язык Spec#, исследовательский проект Microsoft Research, вводит понятие типа без возможности хранения null (non-nullable type) для обеспечения void safety. F#, функциональный язык программирования от Microsoft Research для платформы .NET, реализует аналогичную гарантию, за исключением случаев взаимодействия с другими языками платформы .NET[3].

Null-безопасность на основе объединённых типов

С 2011 года ряд языков программирования поддерживают объединённые типы (union types) и пересекающиеся типы (intersection types), что позволяет выявлять возможные null-указатели уже во время компиляции. Для этого применяется специальный класс Null, где значение null — единственный экземпляр.

Типобезопасная работа с null впервые реализована в языке Ceylon, а затем аналогичная функциональность быстро появилась в TypeScript.

В C# полноценная компиляционная проверка null-безопасности реализована начиная с версии 8. Для обратной совместимости с прежними выпусками языка, эта возможность может быть включена отдельно для проекта или даже для отдельного файла[4].

В Dart поддержка null-безопасности реализована начиная с версии 2.0, с августа 2018 года[5][6].

Среди других языков, где типы по умолчанию не допускают null-значения — Kotlin от JetBrains[7], Rust[8], и Swift от компании Apple.

Примечания

  1. C.A.R. Hoare: Null References: The Billion Dollar Mistake, тезисы выступления на QCon London, 9–12 марта 2009 года. Null References: The Billion Dollar Mistake (англ.). QCon London 2009 (12 марта 2009). Дата обращения: 25 июня 2024. Архивировано 19 января 2009 года.
  2. Bertrand Meyer: Attached Types and their Application to Three Open Problems of Object-Oriented Programming, in ECOOP 2005 (Proceedings of European Conference on Object-Oriented Programming, Edinburgh, 25–29 July 2005), ed. Andrew Black, Lecture Notes in Computer Science 3586, Springer Verlag, 2005, страницы 1–32. Attached Types and their Application to Three Open Problems of Object-Oriented Programming (англ.). ETH Zurich. Дата обращения: 25 июня 2024. Архивировано 25 сентября 2006 года.
  3. Quote of the Week: "What can C# do that F# cannot?" (англ.). Microsoft Dev Blogs. Microsoft. Дата обращения: 25 июня 2024. Архивировано 21 апреля 2016 года.
  4. Nullable reference types (англ.). Microsoft Docs. Дата обращения: 25 июня 2024. Архивировано 8 января 2019 года.
  5. Moore, Kevin Announcing Dart 2 Stable and the Dart Web Platform (англ.). Dart (7 августа 2018). Дата обращения: 25 июня 2024. Архивировано 26 августа 2025 года.
  6. Sound null safety (англ.). Dart. Дата обращения: 25 июня 2024. Архивировано 29 сентября 2025 года.
  7. Null safety—Kotlin (англ.). Kotlin. Дата обращения: 25 июня 2024. Архивировано 12 октября 2025 года.
  8. Defining an Enum - The Rust Programming Language (англ.). doc.rust-lang.org. Дата обращения: 25 июня 2024. Архивировано 9 октября 2025 года.