Пример кода для запуска статического анализатора Clang

Я хотел бы увидеть небольшой, но полный фрагмент кода, который заставит статический анализатор Clang жаловаться. Моя мотивация в основном заключается в том, что я пытаюсь заставить его работать с моим кодом PIC32, и мне нужен способ различать «весь код в порядке» и «на самом деле он ничего не делает». Это также отчасти любопытство, поскольку я сам не могу придумать простой пример.

C89/ANSI или C99 в порядке, и в идеале я бы хотел, чтобы он обнаруживал простую утечку памяти. Мое использование

clang --analyze test.c

person detly    schedule 11.08.2010    source источник


Ответы (1)


Я нашел "ошибку" в своем коде (единственную ;-), которая срабатывает из-за этого, и которая не обнаруживается -Wall. Я приготовил это до следующего

struct elem {
  struct elem *prev;
  struct elem *next;
};

#define ELEM_INITIALIZER(NAME) { .prev = &(NAME), .next = &(NAME), }

struct head {
  struct elem header;
};

#define HEAD_INITIALIZER(NAME) { .header = ELEM_INITIALIZER(NAME.header) }

int main(int argc, char ** argv) {
  struct head myhead = HEAD_INITIALIZER(myhead);
}

Это относительно простая реализация связанного списка, но здесь это не важно. Переменная myhead не используется в обычном применении термина, но для компилятора она используется, т.к. внутри инициализатора берется адрес поля.

clang правильно анализирует это как

/tmp 11:58 <722>% clang --analyze test-clang.c
test-clang.c:25:15: warning: Value stored to 'myhead' during its initialization is never read
  struct head myhead = HEAD_INITIALIZER(myhead);
              ^        ~~~~~~~~~~~~~~~~~~~~~~~~
1 diagnostic generated.

Редактировать: я нашел еще один, который также обнаруживает распространение памяти стека.

char const* myBuggyFunction(void) {
  return (char[len + 1]){ 0 };
}

Это определяется не gcc, open64 или clang с -Wall, а clang с --analyze.

person Jens Gustedt    schedule 15.08.2010
comment
Делает работу, спасибо :) Должен сказать, я придумал самые очевидные и самые креативные кровавые утечки памяти, какие только мог придумать, и это пропустило их все. Ясно, что он знает достаточно, чтобы знать, что я тестировал его. - person detly; 17.08.2010
comment
@detly: было весело, научился лязгать благодаря этому :) для моего любопытства, что такое утечки в контексте статического анализа? - person Jens Gustedt; 17.08.2010
comment
Ну, я не уверен на 100%, но у меня сложилось впечатление, что многие инструменты статического анализа, включая clang, могут обнаруживать потенциальные проблемы с памятью во время выполнения (такие как p = malloc(...); p = q;). Я могу ошибаться в этом. - person detly; 17.08.2010
comment
Хм, могло бы, если бы они каким-то образом жестко закодировали, что malloc выполняет распределение. Разве это не должно быть где-то задокументировано? По крайней мере, в этом тривиальном случае он должен дать вам предупреждение о том, что инициализация не используется :) Но для проблем с динамической памятью есть valgrind, который отлично справляется со своей задачей, поэтому, возможно, они сосредоточат свои усилия на других потенциальных ошибках. - person Jens Gustedt; 17.08.2010
comment
Это кажется разумным. Обычно я не использую динамическую память, так что это не проблема, мне просто было любопытно, подхватит ли она ее. Кроме того, я все равно не могу использовать valgrind, так как это код для PIC32MX (т.е. встроенный). - person detly; 17.08.2010
comment
В этом добавленном примере: вы уверены, что он не должен возвращать const char *? - person detly; 08.11.2010
comment
@detly: T* неявно преобразуется в T const*. У меня это было здесь так, потому что это то, что происходило в реальной жизни: у меня был составной литерал, который передавался другой функции для инициализации, а затем возвращался самой функцией. const или не const может повлиять на серьезность проблемы, поскольку, если это const, компилятору разрешено размещать его не в стеке, а статически в текстовом сегменте. Таким образом, ошибка может быть даже скрыта еще дольше, пока вы не скомпилируете компилятором, который поместит ее в стек. gcc и opencc отличаются, например, этим. - person Jens Gustedt; 08.11.2010