Interested Article - Недостижимый код
- 2020-08-09
- 1
В программировании и теории компиляторов , недостижимым кодом называют часть кода программы, которая ни при каких условиях не может быть исполнена, поскольку является недостижимой в графе потока управления .
Недостижимый код часто относят к одному из типов мёртвого кода , такая терминология обычно применяется при рассмотрении исходного кода программ . Однако в теории компиляторов , эти понятия никак не связаны, мёртвым кодом там называют только достижимый, но не влияющий на вывод программы код .
Основные недостатки наличия в программе недостижимого кода:
- Занимает излишнюю память;
- Является причиной излишнего кэширования инструкций в кэш инструкций CPU — которое также снижает локальность данных;
- Затрудняет поддержку приложений — время и силы могут быть потрачены на поддержку и документирование части кода, которая является недостижимой, а значит никогда не исполняется.
Причины возникновения
Существование недостижимого кода может быть обусловлено разными факторами, например:
- Программные ошибки в сложных условных переходах ;
- Вследствие внутренних преобразований, выполняемых оптимизирующим компилятором ;
- Неполное тестирование новой или модифицированной программы, которому не удалось обнаружить недостижимый код;
- При исправлении одной ошибки, программист создал другую ошибку, которая обходит недостижимый код и не была обнаружена во время тестирования;
- Устаревший код, который не был полностью удалён программистом, так как он был смешан с действующим кодом;
- Устаревший код, который программист забыл удалить;
- Ранее полезный код, который никогда не будет исполнен, так как, в дальнейшем, ввод данных никогда не приведёт к исполнению этого кода;
- Устаревший код, который был намеренно сохранён, но сделан недостижимым, для того чтобы его можно было при необходимости снова включить в программу;
- Отладочные конструкции и остаточные части кода, которые ещё должны быть удалены из программы.
В последних пяти случаях, недостижимый код является унаследованным, то есть код, который был однажды полезным, но сейчас не используется.
Примеры
Рассмотрим следующий пример на языке Си :
int foo(int x, int y)
{
return x + y;
int z = x*y; /* Недостижимый код */
}
Операция
int z = x*y
является недостижимым кодом, так как перед ней выполняется выход из процедуры (операции, стоящие после возврата из процедуры могут и не являться недостижимым кодом, например, если на метку, стоящую после возврата ссылается оператор
goto
).
Анализ
Поиск недостижимого кода в исходном коде может быть выполнен с помощью статического анализа кода . В оптимизирующем компиляторе , выявить и удалить недостижимый код способна оптимизация удаления недостижимого кода , которая находит в графе потока управления (CFG) недостижимые узлы и удаляет их . Простой анализ CFG-графа на недостижимые узлы часто бывает реализован в компиляторе в виде отдельной функции, т. н. сборщика мусора , которая вызывается сразу после преобразований, способных изменять граф потока управления .
Код может становиться недостижимым в результате выполнения других преобразований компилятора над промежуточным представлением , например оптимизации удаления общих подвыражений .
На практике, сложность реализуемого анализа существенно влияет на количество выявляемого недостижимого кода. Например, после
свёртки констант
и простого анализа
потока управления
можно обнаружить, что код внутри оператора
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); /* Недостижимый код */
}
}
Одним из практических решений является подход, выполняющий сначала простой анализ выявления недостижимого кода, а затем использует профилировщик для обработки более сложных случаев. Профилировщик не может доказать, что какой-либо участок кода является недостижимым, но он может быть хорошей эвристикой для нахождения подозрительных узлов, которые, вероятно, являются недостижимыми. После обнаружения этих потенциально недостижимых узлов, можно применить какой-нибудь мощный алгоритм анализа недостижимого кода.
См. также
Примечания
- ↑ Engineering a Compiler — С. 544.
- ↑ Debray, S. K., Evans, W., Muth, R., and De Sutter , B. 2000. от 22 мая 2003 на Wayback Machine . ACM Trans. Program. Lang. Syst. 22, 2 (Mar. 2000), 378—415. ( от 11 сентября 2004 на Wayback Machine )
- ↑ . Aivosto. Дата обращения: 12 июля 2012. 5 августа 2012 года.
- ↑ . Java.net. Дата обращения: 12 июля 2012. Архивировано из 23 сентября 2012 года.
- Компиляторы — принципы, технологии, инструменты — С. 669 ( недостижимый код ), 713 ( мёртвый код ).
- Engineering a Compiler — С. 550.
- А. Ю. Дроздов, А. М. Степаненков. Управляемые пакеты оптимизаций. В Информационные технологии и вычислительные системы , 2004, № 3 ( )
Литература
- Cooper and Torczon. Engineering a Compiler. — Morgan Kaufmann, 2011. — С. 544-550, 593. — ISBN 978-0-12-088478-0 .
- Альфред Ахо, Моника Лам, Рави Сети, Джеффри Ульман. Компиляторы: принципы, технологии и инструментарий = Compilers: Principles, Techniques, and Tools. — 2-е издание. — М. : «Вильямс», 2008. — 1184 с. — 1500 экз. — ISBN 978-5-8459-1349-4 .
- Muchnick, Steven S. . — Morgan Kaufmann Publishers , 1997. — С. -582. — ISBN 1-55860-320-4 .
- 2020-08-09
- 1