Русская Википедия:Мёртвый код

Материал из Онлайн справочника
Перейти к навигацииПерейти к поиску

В теории компиляторов, мёртвым кодом (Шаблон:Lang-en, также отмершим кодом, бесполезным кодом, неиспользуемым кодом) называют код, который может быть исполнен (в существующей на текущий момент версии кодовой базы), исполнялся или мог быть исполнен ранее (до внесения в код на каком-то из моментов его существования изменений, сделавших его бесполезным), но результаты его вычислений не влияют на дальнейшую программу (в частности, не используются)[1][2][3]. Другими словами, это код, определяющий только Шаблон:Нп5 или вообще не определяющий никакие переменные.

При рассмотрении исходного кода, часто используют другое, более общее понятие мёртвого (отмершего) кода, которое, кроме бесполезного кода, включает в себя недостижимый код[4][5].

Наличие мёртвого кода в программе увеличивает её размер, давление на ресурсы (устройства, регистры), тепловыделение и может увеличить время исполнения, не неся при этом никакой пользы. В оптимизирующих компиляторах для выявления и удаления мёртвого и недостижимого кодов на уровне промежуточного представления используются оптимизации удаления мёртвого кода и удаления недостижимого кода. Для поиска мёртвого кода в исходном коде применяются всевозможные анализаторы и детекторы мёртвого кода[4][5]. Такие анализаторы часто бывают встроены в компилятор или IDE и выдают соответствующие предупреждения о наличии в программе мёртвого кода во время её компиляции[6][7][8].

Примеры

Рассмотрим следующий пример на языке Си:

 int foo(int x, int y)
 {
   int z; /* Объявление мёртвой переменной */
   z = x/y; /* Мёртвый код */
   return x*y;
 }

Здесь, операция z = x/y является мёртвым (бесполезным) кодом, так как результат работы этой операции, переменная z, в дальнейшем в программе не используется. Сама переменная z является мёртвой в процедуре foo. Если переменная y равна нулю, то операция, выполняющая бесполезное вычисление, спровоцирует исключение, следовательно её удаление, возможно, способно изменить вывод программы. Оптимизация удаления мёртвого кода удалит операцию z = x/y, только если не будет сомнений в том, что из-за этого не изменится результат работы программы[9].

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

 int foo(void)
 {
   int x = 25;
   return x;
   x = 2*x; /* Недостижимый код */
   return 0; /* Недостижимый код */
 }

Здесь, операции x = 2*x и return 0 не могут быть исполнены ни при каких условиях, так как они происходят после безусловного возврата из процедуры и являются недостижимыми (операции, стоящие после возврата из процедуры могут и не являться недостижимым кодом, например, если на метку, стоящую после возврата ссылается оператор goto). Оптимизация удаления недостижимого кода может удалить эту операцию.

Анализ

Для выявления и удаления бесполезного кода, оптимизация удаления мёртвого кода использует результаты Шаблон:Нп5 (например Шаблон:Нп5) или осуществляет самостоятельный анализ SSA-представления программы. Оптимизация удаления недостижимого кода анализирует граф потока управления и устраняет недостижимые узлы.

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

В исходном коде больших приложений бывает сложно распознать мёртвый код (бесполезный и недостижимый). Для этого могут применяется детекторы мёртвого кода[4][5], выполняющие статический анализ кода. Многие компиляторы и IDE выдают предупреждения об объявленных, но неиспользуемых функциях, методах, классах, переменных[6][7][8].

Мёртвый код и информационная безопасность

Для сокрытия алгоритмов, используемых в программе, с целью защиты интеллектуальной собственности, мёртвый код может добавляется в программу намеренно, в качестве затеняющего преобразования. Такое преобразование призвано увеличить энтропию кода, чтобы затруднить восстановление алгоритма, реализованного в программе. Так же, в целях затенения, в программу может добавляться недостижимый некорректный код: во время работы программы такой участок кода никогда не исполняется и не вызывает ошибок, но дизассемблер или декомпилятор во время работы с этим участком кода могут повести себя непредсказуемо[10][11].

Наличие в программе мёртвого и недостижимого кодов может являться уязвимостью, так как в такие участки кода могут внедряться программные закладки[12][13].

См. также

Примечания

Шаблон:Примечания

Литература

Ссылки

  1. Engineering a Compiler — С. 544.
  2. Компиляторы — принципы, технологии, инструменты — С. 713, 714.
  3. Debray, S. K., Evans, W., Muth, R., and De Sutter, B. 2000. Compiler techniques for code compaction Шаблон:Wayback. ACM Trans. Program. Lang. Syst. 22, 2 (Mar. 2000), 378—415. (summary)
  4. 4,0 4,1 4,2 Шаблон:Cite web
  5. 5,0 5,1 5,2 Шаблон:Cite web
  6. 6,0 6,1 Шаблон:Cite web
  7. 7,0 7,1 Шаблон:Cite web
  8. 8,0 8,1 Шаблон:Cite web
  9. 9,0 9,1 Appel, A. W. Modern Compiler Implementation in Java. — Cambridge University Press, 2004. — С. 360. — ISBN 0-511-04286-8.
  10. И. Ю. Иванов / Киевский национальный университет им. Тараса Шевченко / О проблемах защиты интеллектуальной собственности в программных системах // Проблеми прграмування. — 2006. — № 2-3 Спеціальний випуск — С. 68-72. (текст Архивировано)
  11. Обфускация и её преодоление // Лаборатория взлома. — Май 2006. — С. 8-13. (текст Архивировано)
  12. Торшенко Ю. А. / СПб ГУ ИТМО / Модель и метод обнаружения уязвимостей на начальных этапах промышленного проектирования программного продукта. — 2008. (текст Архивировано)
  13. Сакулина М. С. / Выявление и устранение «мертвого кода» с использованием технологии программирования IBM Rational Application Developer. (текст Архивировано)