Есть ли способ получить предупреждение о неиспользуемых функциях? - PullRequest
45 голосов
/ 01 февраля 2012

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

Вот пример:

foo.c (допустим foo.h):

void foo() {
   ....
}

void bar() {
   ....
}

main.c:

#include <stdio.h>
#include "foo.h"  

int main(void)  {
    bar();
    return 0;
}

В этом примере я хотел бы получить предупреждение о том, что foo() не используется.

Существует опция -Wunused-function gcc:

-Wunused-function

Предупреждать всякий раз, когда статическая функция объявлена, но не определена, или если не встроенная статическая функция не используется. Это предупреждение включается -Wall.

но это только для статических функций - оно не выдаст предупреждение в примере выше.

Я также приму предложения инструментов / скриптов / других компиляторов, которые могут сделать это для меня - хотя я бы предпочел придерживаться gcc, если это возможно.

Ответы [ 5 ]

43 голосов
/ 17 февраля 2012

Caolan Mc Namara , разработчик LibreOffice, создал небольшой инструмент для обнаружения подобных вещей в исходном коде LibreOffice. У них было около тысячи функций и методов, неиспользованных в LibreOffice. Его инструмент является ключевым элементом для их удаления.

Это называется callcatcher . Может

собирать определенные функции / методы и вычитать вызываемые / ссылающиеся

Он работает непосредственно на выходе ассемблера и поэтому работает только для архитектуры x86 и x86_64. Он может производить вывод как this . Вы можете интегрировать его с вашим традиционным вызовом компиляции и связывания с gcc.

Каолан согласен с тем, что он должен стать плагином gcc.

3 голосов
/ 01 февраля 2012

Я знаю, что вы спрашивали предупреждения и предпочитаете не использовать опцию gcc, но это действительно просто.

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

со страницы руководства gcc:

- ГЦ-разделы --no-ГЦ-секции Включить сбор мусора из неиспользуемых разделов ввода. Он игнорируется для целей, которые не поддерживают эту опцию. Поведение по умолчанию (не выполнение этой сборки мусора) можно восстановить, указав --no-gc-section в командной строке.

- gc-section определяет, какие входные разделы используются при проверке символов и перемещений. Раздел, содержащий символ ввода, и все разделы, содержащие символы, неопределенные в командной строке, будут сохранены, как и разделы, содержащие символы, на которые ссылаются динамические объекты. Обратите внимание, что при создании разделяемых библиотек компоновщик должен предполагать, что на любой видимый символ ссылаются. Как только этот начальный набор разделов был определен, компоновщик рекурсивно помечает как использованный любой раздел, на который ссылаются их перемещения. См. --Entry и --undefined.

Эта опция может быть установлена ​​при выполнении частичной ссылки (активируется с опцией -r). В этом случае корень хранимых символов должен быть явно указан либо с помощью параметра --entry или --undefined, либо с помощью команды «ENTRY» в сценарии компоновщика.

3 голосов
/ 01 февраля 2012

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

Тогда, в общем случае, я бы понял, что не будет разумно предоставлять его (потому что, например, связанный libc, вероятно,имеет много функций, которые не нужны вашему приложению).Кроме того, приложение может использовать dlsym трюки для достижения явно не вызываемой функции ...

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

Вы также можете использовать методы профилирования для динамического неиспользования (не называемого) функций.

Не стесняйтесь спрашивать меня по электронной почте.

1 голос
/ 15 февраля 2012

gprof это самое простое решение, я думаю.Я скомпилировал пример программы, которую вы установили, с опцией -pg, чтобы мы получили gmon.out, когда мы запустим a.out (которую gprof может использовать позже), а затем я наконец запустил gprof -z a.out gmon.out | tee output.txt.Я мог бы найти вашу функцию foo в неиспользованном списке!т.е. называется 0 раз.-z - это опция, которую вы должны использовать вместе с gprof для отслеживания неиспользуемых подпрограмм.

Благодаря этому потоку для соответствующего указателя!

PS: gprof выкинул множество других неиспользуемых библиотечных функций вместе с вашей неиспользуемой функцией foo.Я серьезно не знаю, как это отфильтровать:)

1 голос
/ 01 февраля 2012

Eclipse CDT имеет анализ кода, который вы можете установить для отметки неиспользуемых статических функций и объявлений неиспользуемых функций (среди других полезных вещей).Как уже говорилось, только компоновщик мог сказать, что определенная (нестатическая) функция не использовалась в определенном двоичном файле ...

...