В компьютерном программировании, недостижимый код является частью источника код программы, который никогда не может быть выполнен из-за отсутствия потока управления пути к коду из остальной части программы.
Недостижимый код иногда также называют мертвым кодом, хотя мертвый код может также относиться к коду, который выполняется, но не влияет на вывод программы.
Недоступный код обычно считается нежелательным по нескольким причинам:
Однако недосягаемость Возможный код может иметь некоторые законные применения, например, предоставление библиотеки функций для вызова или перехода вручную через отладчик, когда программа останавливается после точки останова. Это особенно полезно для изучения и распечатки внутреннего состояния программы. Может иметь смысл иметь такой код в поставляемом продукте, чтобы разработчик мог подключить отладчик к работающему экземпляру клиента.
Недостижимый код может существовать по многим причинам, например:
Устаревший код который когда-то был полезен, но больше не используется и не требуется. Но недоступный код также может быть частью сложной библиотеки, модуля или подпрограммы, где он полезен другим или в условиях, которые не выполняются в конкретном сценарии.
Примером такого условно недоступного кода может быть реализация общей функции форматирования строк в библиотеке времени выполнения компилятора, которая содержит сложный код для обработки всех возможных аргументов, из которых фактически используется только небольшое подмножество. Компиляторы обычно не могут удалить неиспользуемые участки кода во время компиляции, так как поведение в значительной степени определяется значениями аргументов во время выполнения.
В этом фрагменте кода C:
int foo (int X, int Y) {return X + Y; int Z = X * Y; }
определение int Z = X * Y;никогда не достигается, поскольку функция всегда возвращает до него. Следовательно, Zне нужно ни выделять память, ни инициализировать.
Apple SSL / TLS от февраля 2014 года содержала серьезную уязвимость безопасности, официально известную как CVE - 2014-1266 и неофициально как «ошибка перехода». Соответствующий фрагмент кода:
static OSStatus SSLVerifySignedServerKeyExchange (SSLContext * ctx, bool isRsa, SSLBuffer signedParams, uint8_t * signature, UInt16 signatureLen) {OSStatus err;... if ((err = SSLHashSHA1.update (hashCtx, serverRandom))! = 0) перейти к ошибке; if ((err = SSLHashSHA1.update (hashCtx, signedParams))! = 0) перейти к ошибке; перейти к неудаче; if ((err = SSLHashSHA1.final (hashCtx, hashOut))! = 0) goto fail;... сбой: SSLFreeBuffer (signedHashes); SSLFreeBuffer (hashCtx); return err; }
Здесь два последовательных вызова goto fail
. В синтаксисе языка C второе является безусловным и, следовательно, всегда пропускает вызов SSLHashSHA1.final
. Как следствие, err
будет содержать статус операции обновления SHA1, и проверка подписи никогда не завершится ошибкой.
Здесь недостижимый код - это вызов final
функция. Есть несколько методов кодирования, которые могли бы предотвратить эту ошибку, например, проверка кода, правильное использование отступов или блочной структуры и анализ тестового покрытия. Применение компилятора Clang с опцией -Weverything
включает анализ недостижимого кода, который вызовет сигнал тревоги для этого кода.
In C ++, для некоторых конструкций указано поведение undefined. Компилятор может реализовать любое поведение или ничего, и обычно оптимизирующий компилятор предполагает, что код недоступен.
Обнаружение недоступного кода - это форма анализа потока управления, чтобы найти код, который никогда не будет достигнут ни в одном из возможных состояний программы. В некоторых языках (например, Java ) некоторые формы недоступного кода явно запрещены. Оптимизация, которая удаляет недоступный код, известна как устранение мертвого кода.
. Код может стать недоступным в результате преобразований, выполняемых оптимизирующим компилятором (например, устранение общего подвыражения ).
На практике сложность анализа оказывает значительное влияние на количество обнаруживаемого недостижимого кода. Например, сворачивание констант и простой анализ потока показывают, что внутренняя часть оператора if в следующем коде недоступна:
int N = 2 + 1; if (N == 4) {/ * unreachable * /}
Однако требуется гораздо больше усилий, чтобы выяснить, что соответствующий блок недоступен в следующем коде:
double X = sqrt (2) ; if (X>5) {/ * unreachable * /}
Техника устранения недостижимого кода относится к тому же классу оптимизаций, что и устранение мертвого кода и удаление избыточного кода.
В некоторых случаях практический подход может заключаться в сочетании простых критериев недоступности и использования профилировщика для обработки более сложных случаев. Профилирование в целом ничего не может доказать о недостижимости фрагмента кода, но может быть хорошей эвристикой для поиска потенциально недостижимого кода. Как только подозрительный фрагмент кода обнаружен, можно использовать другие методы, такие как более мощный инструмент анализа кода или даже анализ вручную, чтобы решить, действительно ли код недоступен.