Мёртвый кодВ теории компиляторов, мёртвым кодом (англ. dead code, также отмершим кодом, бесполезным кодом, неиспользуемым кодом) называют код, который может быть исполнен (в существующей на текущий момент версии кодовой базы), исполнялся или мог быть исполнен ранее (до внесения в код на каком-то из моментов его существования изменений, сделавших его бесполезным), но результаты его вычислений не влияют на дальнейшую программу (в частности, не используются)[1][2][3]. Другими словами, это код, определяющий только мёртвые переменные[англ.] или вообще не определяющий никакие переменные. При рассмотрении исходного кода, часто используют другое, более общее понятие мёртвого (отмершего) кода, которое, кроме бесполезного кода, включает в себя недостижимый код[4][5]. Наличие мёртвого кода в программе увеличивает её размер, давление на ресурсы (устройства, регистры), тепловыделение и может увеличить время исполнения, не неся при этом никакой пользы. В оптимизирующих компиляторах для выявления и удаления мёртвого и недостижимого кодов на уровне промежуточного представления используются оптимизации удаления мёртвого кода и удаления недостижимого кода. Для поиска мёртвого кода в исходном коде применяются всевозможные анализаторы и детекторы мёртвого кода[4][5]. Такие анализаторы часто бывают встроены в компилятор или IDE и выдают соответствующие предупреждения о наличии в программе мёртвого кода во время её компиляции[6][7][8]. ПримерыРассмотрим следующий пример на языке Си: int foo(int x, int y)
{
int z; /* Объявление мёртвой переменной */
z = x/y; /* Мёртвый код */
return x*y;
}
Здесь, операция Применительно к исходному коду, недостижимый код часто называют мёртвым, хотя с точки зрения теории компиляторов это разные вещи. Рассмотрим следующий пример: int foo(void)
{
int x = 25;
return x;
x = 2*x; /* Недостижимый код */
return 0; /* Недостижимый код */
}
Здесь, операции АнализДля выявления и удаления бесполезного кода, оптимизация удаления мёртвого кода использует результаты анализа потока данных[англ.] (например анализа активных переменных[англ.]) или осуществляет самостоятельный анализ SSA-представления программы. Оптимизация удаления недостижимого кода анализирует граф потока управления и устраняет недостижимые узлы. При работе с бесполезным кодом используют консервативный подход: если операция, выполняющая бесполезное действие, может провоцировать исключение, и существует ненулевая вероятность того, что это исключение влияет на вывод программы, то не нужно удалять эту операцию[9]. В исходном коде больших приложений бывает сложно распознать мёртвый код (бесполезный и недостижимый). Для этого могут применяется детекторы мёртвого кода[4][5], выполняющие статический анализ кода. Многие компиляторы и IDE выдают предупреждения об объявленных, но неиспользуемых функциях, методах, классах, переменных[6][7][8]. Мёртвый код и информационная безопасностьДля сокрытия алгоритмов, используемых в программе, с целью защиты интеллектуальной собственности, мёртвый код может добавляется в программу намеренно, в качестве затеняющего преобразования. Такое преобразование призвано увеличить энтропию кода, чтобы затруднить восстановление алгоритма, реализованного в программе. Так же, в целях затенения, в программу может добавляться недостижимый некорректный код: во время работы программы такой участок кода никогда не исполняется и не вызывает ошибок, но дизассемблер или декомпилятор во время работы с этим участком кода могут повести себя непредсказуемо[10][11]. Наличие в программе мёртвого и недостижимого кодов может являться уязвимостью, так как в такие участки кода могут внедряться программные закладки[12][13]. См. такжеПримечания
Литература
Ссылки |