Безопасность 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.

Примечания