Введение
В программировании обнаружение того, находится ли переменная в заданных пределах перед использованием.
В компьютерном программировании проверка границ — это любой метод определения, находится ли переменная в определенных пределах перед ее использованием. Обычно это делается для того, чтобы убедиться, что число соответствует заданному типу (проверка диапазона) или что переменная, используемая в качестве индекса массива, находится в пределах допустимых значений для этого массива (проверка индекса). Неуспешная проверка границ обычно приводит к генерации сигнала об ошибке или исключению. Поскольку выполнение проверки границ при каждом использовании может быть затратным по времени, она не всегда выполняется. Удаление проверок границ — это метод оптимизации компилятора, который устраняет ненужные проверки границ.
Проверка дальности
Проверка диапазона – это проверка, удостоверяющая, что число находится в заданном диапазоне; например, для гарантии того, что значение, которое собираются присвоить 16-битовому целому числу, не превышает его пределы (то есть, проверка на переполнение). Это отличается от проверки типов. Другие проверки диапазона могут быть более строгими; например, переменная для хранения номера месяца в календаре может быть объявлена с ограничением на диапазон значений от 1 до 12.
Проверка индекса
Индексная проверка означает, что во всех выражениях, индексирующих массив, значение индекса проверяется на соответствие границам массива (которые были установлены при определении массива), и если индекс выходит за границы, дальнейшее выполнение приостанавливается из-за возникновения ошибки. Поскольку чтение или, особенно, запись значения за пределами массива может привести к сбоям в работе программы, аварийному завершению или создать уязвимости в системе безопасности (см. переполнение буфера), индексная проверка является частью многих языков программирования высокого уровня. Ранние компилируемые языки программирования с возможностью индексной проверки включали ALGOL 60, ALGOL 68 и Pascal, а также интерпретируемые языки, такие как BASIC. Многие языки программирования, например C, не выполняют автоматическую проверку границ для повышения производительности. Однако это приводит к тому, что многие ошибки "за единицу" и переполнения буфера остаются необнаруженными. Многие программисты считают, что эти языки слишком сильно жертвуют безопасностью ради скорости выполнения. В своей лекции, посвященной премии Тьюринга в 1980 году, К. А. Р. Хоар описал свой опыт разработки языка ALGOL 60, который включал индексную проверку, и сказал:
"Следствием этого принципа было то, что каждое вхождение каждого индекса каждой индексируемой переменной при каждом обращении проверялось во время выполнения как на верхнюю, так и на нижнюю объявленную границу массива. Много лет спустя мы спросили наших клиентов, хотели бы они, чтобы мы предоставили возможность отключить эти проверки ради повышения эффективности в производственной среде. Они единогласно попросили нас этого не делать, поскольку уже знали, как часто возникают ошибки индексации в производственной среде, и их необнаружение могло привести к катастрофическим последствиям. С ужасом и тревогой я отмечаю, что даже в 1980 году разработчики языков и пользователи не усвоили этот урок. В любой уважаемой области инженерии несоблюдение таких элементарных мер предосторожности давно было бы незаконным." Основные языки, обеспечивающие проверку во время выполнения, включают Ada, C#, Haskell, Java, JavaScript, Lisp, PHP, Python, Ruby, Rust и Visual Basic. Языки D и OCaml имеют проверку границ во время выполнения, которая включается или отключается с помощью переключателя компилятора. В C++ проверка во время выполнения не является частью языка, а является частью STL и включается с помощью переключателя компилятора (GLIBCXX_DEBUG=1 или LIBCPP_DEBUG=1). C# также поддерживает небезопасные области: разделы кода, которые (среди прочего) временно отключают индексную проверку для повышения производительности. Они полезны для ускорения небольших критически важных узких мест без ущерба для безопасности всей программы. Язык программирования JS++ способен анализировать, выходит ли индекс массива или ключ карты за пределы допустимого диапазона во время компиляции, используя существующие типы, которые представляют собой номинальный тип, описывающий, находится ли индекс или ключ в пределах границ или за их пределами, и направляет генерацию кода. Было показано, что использование существующих типов добавляет всего 1 мс к времени компиляции.
Проверка границ оборудования
Безопасность, обеспечиваемая проверкой границ, неизбежно требует затрат времени процессора, если проверка выполняется программно; однако, если проверки могут выполняться аппаратно, то безопасность может быть обеспечена "бесплатно", без влияния на время выполнения. Одной из первых систем с аппаратной проверкой границ был мейнфрейм серии ICL 2900, представленный в 1974 году. Компьютер VAX имеет ассемблерную инструкцию INDEX для проверки индексов массива, которая принимает шесть операндов, все из которых могут использовать любой режим адресации VAX. Компьютеры B6500 и аналогичные компьютеры Burroughs выполняли проверку границ аппаратно, независимо от того, какой язык программирования был скомпилирован для получения машинного кода. Ограниченное число более поздних процессоров имеет специализированные инструкции для проверки границ, например, инструкция CHK2 в серии Motorola 68000. Исследования в области использования встроенного в x86 блока управления виртуальной памятью для обеспечения безопасности доступа к массивам и буферам ведутся как минимум с 2005 года. В 2015 году Intel представила расширения Intel MPX в архитектуре процессора Skylake, которые хранят границы в регистре процессора и таблице в памяти. По состоянию на начало 2017 года, как минимум, GCC поддерживает расширения MPX.