Вопрос по c, gcc, gcc-warning – Как заставить gcc предупредить о возвращении адреса локальных переменных?

12

Сgcc 4.4.5, у меня есть предупреждение со следующим кодом.

char *f(void)
{
    char c;
    return &c;
}

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

char *f(void)
{
    char c;
    char *p = &c;
    return p;
}

Я слышал, что указатель-анализ сложно в C, но можетgcc предупредить о таком коде?

Почему именно неверный адрес локальных переменных и каким он должен быть? (C новичком здесь) Yahya Uddin
Clang намного лучше для этого, а также включает в себя инструмент статического анализа, который должен увидеть такую ошибку. Вы должны попробовать, если можете. Macmade
Возможно, лучше, чтобы кто-то из ваших коллег рассмотрел ваш код и использовал стандарт кодирования? Ed Heal

Ваш Ответ

2   ответа
9

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

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


Обратите внимание, что даже можно спорить, действительно ли существует проблема в функцииf() в вашей программе. функцияh() ниже явно хорошо, хотя вызывающий код не должен использоватьp после возвращения:

char *p;

void h(void)
{
    char c;
    p = &c;
}

Другой статический анализатор, который я могу порекомендовать,Анализ стоимости Frama-C (Я один из разработчиков). Этот не оставляет ложных отрицаний, для некоторых семейств ошибок (включая висячие указатели), при использовании в контролируемых условиях.

char *f(void)
{
    char c;
    return &c;
}

char *g(void)
{
    char c;
    char *p = &c;
    return p;
}

$ frama-c -val -lib-entry -main g r.c
...
r.c:11:[value] warning: locals {c} escaping the scope of g through \result
...
$ frama-c -val -lib-entry -main f r.c
...
r.c:4:[value] warning: locals {c} escaping the scope of f through \result
... 

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

h.c:7:[value] warning: locals {c} escaping the scope of h through p

Настоящая ошибка, характеризуемая словом & # x201C; assert & # x201D; в выводе Frama-C, если функция вызываетh() а затем используетp:

void caller(void)
{
  char d;
  h();
  d = *p;
}

$ frama-c -val -lib-entry -main caller h.c
...
h.c:7:[value] warning: locals {c} escaping the scope of h through p
...
h.c:13:[kernel] warning: accessing left-value p that contains escaping addresses; assert(Ook)
h.c:13:[kernel] warning: completely undefined value in {{ p -> {0} }} (size:<32>).

Анализ стоимости Frama-C называетсяконтекстно-зависимый, Анализирует функциюh() для каждого вызова со значениями, которые фактически передаются ему. Он также анализирует код, который приходит после вызоваh() в функцииcaller() со значениями, которые на самом деле могут быть возвращеныh(), Это дороже, чем контекстно-нечувствительный анализ, который обычно делают Clang или GCC, но более точный.

1

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

Хотя gcc здесь не будет жаловаться, он будет предупреждать с использованием указателя следующим образом:

char *f(const char *x)
{
  char *y = x;
  ...
}

Опять же, он может видеть без каких-либо сомнений, что вы удаляете «const». квалификатор в этом определении.

Другой утилитой, которая обнаружит эту проблему, является шина (http://splint.org).

Похожие вопросы