Clang Static Analyzer неожиданное предупреждение указателя NULL

У меня есть следующий код:

int s[4096];
unsigned char o = 0;

int main(void) {
    int *n;
    return ((char *) (s + o)) == 0 ? *n : 0;
}

Когда я запускаю Clang Static Analyzer для этого кода, он предупреждает меня, что я разыменовываю n, потому что (char *) (s + o) является нулевым указателем, а это не так (я даже могу распечатать его и получить адрес, который определенно не равен нулю).

Что мне не хватает?

Снимок экрана Clang Analyzer

Я замечаю, что удаление приведения (char *) приводит к исчезновению предупреждения.


person rid    schedule 30.10.2019    source источник
comment
Он предупреждает вас, потому что технически условие может оцениваться как истинное, и в этом случае вы разыменовываете неинициализированный указатель.   -  person tkausl    schedule 30.10.2019
comment
@tkausl, это имеет смысл, но я не могу понять, при каких условиях это может быть правдой. Для любого значения o это все равно не будет правдой. И это единственный кодовый путь во всей программе, поэтому ни s, ни o не могут иметь никаких других значений, кроме тех, что указаны в программе. Я также заметил, что удаление приведения (char *) приводит к исчезновению предупреждения.   -  person rid    schedule 30.10.2019
comment
если o больше 4096, то это UB, тогда может быть правдой   -  person OznOg    schedule 30.10.2019
comment
@OznOg, но o - это unsigned char, поэтому он может иметь значения только между 0 и 255.   -  person rid    schedule 30.10.2019
comment
Хорошо, :) Думаю, вы многого ожидаете от компилятора :)   -  person OznOg    schedule 30.10.2019
comment
@OznOg, статический анализатор Clang до сих пор работал очень хорошо, я впервые вижу что-то похожее на ложное срабатывание. Но я могу ошибаться, и может быть что-то, чего я просто не вижу.   -  person rid    schedule 30.10.2019
comment
Давайте рассмотрим это шаг за шагом. (char *) (s + o), уменьшается до (char *) s с o == 0. Теперь (char *)s не может быть равным нулю, если только распределитель памяти ОС не поместил его в абсолютный 0 адрес памяти, то же самое касается только s. У статических анализаторов есть ограничения, а также имейте в виду, что правила для языка различаются в зависимости от версии диалекта и компилятора.   -  person Javier Silva Ortíz    schedule 30.10.2019
comment
@JavierSilvaOrtíz, действительно, мне это кажется ошибкой, тем более что удаление приведения приводит к исчезновению предупреждения, даже если условие одинаково ложно с приведением или без него.   -  person rid    schedule 30.10.2019


Ответы (1)


Я тестировал с помощью Clang Static Analyzer версии 8. Версия 10 больше не выдает предупреждение.

person rid    schedule 30.10.2019