Pull to refresh

Comments 20

1) Если проект использует какую-то библиотеку, скорее всего из нее он вызывает всего несколько функций, но мы же не называем остальной код этой библиотеки мертвым и не удаляем его.

2) Если это наш код и он не нужен временно, его конечно можно удалить, но потом будет сложно искать его в истории контроля версий, т. к. для этого нужно помнить, где он был..

Мне тоже не нравится мертвый код, но приведенные выше соображения мешают избавляться от него "в безусловном порядке".

1) Если проект использует какую-то библиотеку, скорее всего из нее он вызывает всего несколько функций, но мы же не называем остальной код этой библиотеки мертвым и не удаляем его.

Ну вообще тут возможны варианты. Если библиотека статическая, то из нее будут выброшены объектные файлы, на содержимое которых нет ссылок. А если компилятор и линкер поддерживают IPO (interprocedural optimization), то выкидывание неиспользуемого кода будет жощще и из библиотеки будут выкинуты вообще все функции, на которые нет ссылок.

2) Если это наш код и он не нужен временно, его конечно можно удалить, но потом будет сложно искать его в истории контроля версий, т. к. для этого нужно помнить, где он был…

Дык /* многострочные комменты */ же ж!
Или блоки #if 0 / #endif, если речь о C или С++.

Мне тоже не нравится мертвый код, но приведенные выше соображения мешают избавляться от него «в безусловном порядке».

Нормально все.
Гораздо хуже, когда библиотека или фреймворк настолько суровые, что внутри себя используют огромную кучу всякого. В результате использование даже маленькой части функционала приводит к раздуванию кода.
Например, если в программе, использующей фреймворк Qt и собранной статически, просто открыть файл (QFile), то код моментально раздуется на несколько сот килобайт. А все потому, что в коде есть проверки на то, что имя файла — это не URL-адрес. А проверка на URL использует зашитый в программу список «известных сайтов». И хотя формально это не мертвый код, вряд ли он когда-либо понадобится среднестатистической программе.
Причем тут линковка, в статье речь о выкидывании мертвого кода ИЗ ИСХОДНИКОВ. Я понимаю, что он НЕ слинкуется в exe-шник, даже если он и НЕ закомментарен, но нигде не вызывается. Но статья о том, что в исходниках не должно быть такого кода.

Если это наш код и он мертвый - значит что-то у нас не так. Кроме нюансов, но тогда он саспендится и там подробный коммент.

Согласен, как-то так и делаем.

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

Вас послушать дак любой benchmark (алгоритма или железа) или wipe data является мёртвым кодом.

Если benchmark плохо написан, то да. Надо или возвращать результат вычислений из программы или говорить компилятору не делать оптимизаций. С этим сталкивался, наверное, автор любого бенчмарка, вот например AnTuTu.

А насчёт wipe data, зависит от того каких данных — если на диске, то это видимый результат, а если в памяти, то такой код тоже может быть удалён.

Надо или возвращать результат вычислений из программы

И получить overhead на обман компилятора и работать это будет пока компилятор не поумнеет и не поймет что вы возвращаете результат в никуда.

или говорить компилятору не делать оптимизаций

не делать всех оптимизаций? тогда мы получаем benchmark совсем другого неоптимизированного кода. КМК это повод для warning но никак не для слепой оптимизации.

если на диске, то это видимый результат, а если в памяти, то такой код тоже может быть удалён.

Дак в статье и написано что нужно "обманывать" компилятор чтобы программа работала как положено. Стирание памяти это не только пароли, но и часть защиты от отладки\взлома например. Что касается записи на диск - видимым будет результат последней записи, значит предыдущие 10 проходов можно оптимизировать, а если следом DeleteFileA дергается то и последний проход не нужен.

Я понимаю когда undefined behavior, тут я не совсем согласен с логикой, но да, мы имеем то что имеем.

Что если это будет управляющий регистр, или порт вывода?

Скорее всего такой код будет написан или в виде ассемблерной вставки или обложен volatile.

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

хз, такой код может иметь влияние при отладке или для расширения внешними приложениями.

В том случае, когда код действительно "мертвый" - согласен с автором. Но есть случаи, когда данные встраиваются в код (ну или код в данные). Например объявляем функцию/процедуру на ассемблере (псевдоязык - нам главное в сегмент кода поместить массив из байт)

void MyDeathCode() {

asm db AA,BB,CC,DD,0A,0B,0C,OD

}

Этот "код", хотя прямых вызовов его и нет - может быть использован и как хранилище для какого-то набора данных, так и быть вызван путем взятия указателя на начало процедуры + смещение на нужный нам участок от начала (указатель + смещение) и ничто не мешает в набор db поместить исполняемый код.

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

Так что достоверно определить мертвый это код, или нет нереально.

Как это можно сделать в C или C++ без undefined behavior?

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

Имхо, си тем и прекрасен что выстрелить в ногу в нем можно и через ухо :)

>… добавляете к этому адресу смещение что бы получить указатель на адрес возврата из данной функции. Прописываете по этому указателю…

Уже в этот момент будет undefined behavior.

Что это, перевод какой-то статьи из 80-х годов прошлого века?

Sign up to leave a comment.

Articles