Interested Article - Недостижимый код

В программировании и теории компиляторов , недостижимым кодом называют часть кода программы, которая ни при каких условиях не может быть исполнена, поскольку является недостижимой в графе потока управления .

Недостижимый код часто относят к одному из типов мёртвого кода , такая терминология обычно применяется при рассмотрении исходного кода программ . Однако в теории компиляторов , эти понятия никак не связаны, мёртвым кодом там называют только достижимый, но не влияющий на вывод программы код .

Основные недостатки наличия в программе недостижимого кода:

  • Занимает излишнюю память;
  • Является причиной излишнего кэширования инструкций в кэш инструкций 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);  /* Недостижимый код */
   }
 }

Одним из практических решений является подход, выполняющий сначала простой анализ выявления недостижимого кода, а затем использует профилировщик для обработки более сложных случаев. Профилировщик не может доказать, что какой-либо участок кода является недостижимым, но он может быть хорошей эвристикой для нахождения подозрительных узлов, которые, вероятно, являются недостижимыми. После обнаружения этих потенциально недостижимых узлов, можно применить какой-нибудь мощный алгоритм анализа недостижимого кода.

См. также

Примечания

  1. Engineering a Compiler — С. 544.
  2. 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 )
  3. . Aivosto. Дата обращения: 12 июля 2012. 5 августа 2012 года.
  4. . Java.net. Дата обращения: 12 июля 2012. Архивировано из 23 сентября 2012 года.
  5. Компиляторы — принципы, технологии, инструменты — С. 669 ( недостижимый код ), 713 ( мёртвый код ).
  6. Engineering a Compiler — С. 550.
  7. А. Ю. Дроздов, А. М. Степаненков. Управляемые пакеты оптимизаций. В Информационные технологии и вычислительные системы , 2004, № 3 ( )

Литература

Источник —

Same as Недостижимый код