В программировании и теории компиляторов, недостижимым кодом называют часть кода программы, которая ни при каких условиях не может быть исполнена, поскольку является недостижимой в графе потока управленияEngineering a Compiler — С. 544.Debray, S. K., Evans, W., Muth, R., and De Sutter, B. 2000. Compiler techniques for code compaction . ACM Trans. Program. Lang. Syst. 22, 2 (Mar. 2000), 378—415. (summary ).
Недостижимый код часто относят к одному из типов мёртвого кода, такая терминология обычно применяется при рассмотрении исходного кода программ. Однако в теории компиляторов, эти понятия никак не связаны, мёртвым кодом там называют только достижимый, но не влияющий на вывод программы кодКомпиляторы — принципы, технологии, инструменты — С. 669 (недостижимый код), 713 (мёртвый код)..
Основные недостатки наличия в программе недостижимого кода: Занимает излишнюю память; Является причиной излишнего кэширования инструкций в кэш инструкций CPU — которое также снижает локальность данных; Затрудняет поддержку приложений — время и силы могут быть потрачены на поддержку и документирование части кода, которая является недостижимой, а значит никогда не исполняется.
Причины возникновения Существование недостижимого кода может быть обусловлено разными факторами, например: Программные ошибки в сложных условных переходах; Вследствие внутренних преобразований, выполняемых оптимизирующим компилятором; Неполное тестирование новой или модифицированной программы, которому не удалось обнаружить недостижимый код; При исправлении одной ошибки, программист создал другую ошибку, которая обходит недостижимый код и не была обнаружена во время тестирования; Устаревший код, который не был полностью удалён программистом, так как он был смешан с действующим кодом; Устаревший код, который программист забыл удалить; Ранее полезный код, который никогда не будет исполнен, так как, в дальнейшем, ввод данных никогда не приведёт к исполнению этого кода; Устаревший код, который был намеренно сохранён, но сделан недостижимым, для того чтобы его можно было при необходимости снова включить в программу; Отладочные конструкции и остаточные части кода, которые ещё должны быть удалены из программы. В последних пяти случаях, недостижимый код является унаследованным, то есть код, который был однажды полезным, но сейчас не используется.
Примеры Рассмотрим следующий пример на языке Си:
int foo(int x, int y) { return x + y; int z = x*y; /* Недостижимый код */
Операция int z = x*y является недостижимым кодом, так как перед ней выполняется выход из процедуры (операции, стоящие после возврата из процедуры могут и не являться недостижимым кодом, например, если на метку, стоящую после возврата ссылается оператор goto).
Анализ Поиск недостижимого кода в исходном коде может быть выполнен с помощью статического анализа кода. В оптимизирующем компиляторе, выявить и удалить недостижимый код способна оптимизация удаления недостижимого кода, которая находит в графе потока управления (CFG) недостижимые узлы и удаляет ихEngineering a Compiler — С. 550.. Простой анализ CFG-графа на недостижимые узлы часто бывает реализован в компиляторе в виде отдельной функции, т. н. сборщика мусора, которая вызывается сразу после преобразований, способных изменять граф потока управленияА. Ю. Дроздов, А. М. Степаненков. Управляемые пакеты оптимизаций. В Информационные технологии и вычислительные системы, 2004, № 3 (текст ).
Код может становиться недостижимым в результате выполнения других преобразований компилятора над промежуточным представлением, например оптимизации удаления общих подвыражений.
На практике, сложность реализуемого анализа существенно влияет на количество выявляемого недостижимого кода. Например, после свёртки констант и простого анализа потока управления можно обнаружить, что код внутри оператора if в следующем примере является недостижимым:
int foo(void) { int n = 2 + 1; if (n > 4)
printf("%d", n); /* Недостижимый код */
Однако, для того чтобы выявить недостижимый код в следующем примере, необходимо применить гораздо более сложный алгоритм анализа:
int foo(void) { double x = sqrt(2); if (x > 4)
printf("%lf", x); /* Недостижимый код */
Одним из практических решений является подход, выполняющий сначала простой анализ выявления недостижимого кода, а затем использует профилировщик для обработки более сложных случаев. Профилировщик не может доказать, что какой-либо участок кода является недостижимым, но он может быть хорошей эвристикой для нахождения подозрительных узлов, которые, вероятно, являются недостижимыми. После обнаружения этих потенциально недостижимых узлов, можно применить какой-нибудь мощный алгоритм анализа недостижимого кода.
См. также Мёртвый код Удаление мёртвого кода Удаление недостижимого кода
Примечания
Литература
Категория:Теория компиляторов Категория:Исходный код