Почему запись в неинициализированный указатель не вызывает предупреждения?

#c #pointers #gcc #initialization #compiler-warnings

#c #указатели #gcc #инициализация #компилятор-предупреждения

Вопрос:

Почему я могу сделать следующее?

 char *name;
scanf("s", name);
printf("%sn", name);
 

И программа / компилятор не выдает предупреждения? Я думал, что, поскольку name указатель не инициализирован, компилятор (или, возможно, среда выполнения) выдаст предупреждение / ошибку, в которой говорится, что он пытается выполнить запись на неинициализированный адрес памяти.

Комментарии:

1. Потому что ты не проходишь мимо -Wall (или -Wuninitialized )?

2. Это может быть трудно обнаружить во время компиляции из-за проблемы с остановкой, и такие проверки обычно не выполняются во время выполнения из-за снижения производительности. Если вам нужны подобные проверки, поищите такие инструменты, как valgrind, AddressSanitizer и т.д.

3. Если вы используете gcc, обратите внимание, что для того, чтобы он даже пытался перехватить использование неинициализированных переменных во время компиляции, вы должны включить оптимизацию. Попробуй -O -Wall .

4. @NateEldredge godbolt.org/z/ExqGcT не включает оптимизацию, но использует -Wall и улавливает ее.

5. @Siguza круто, на самом деле я получаю это только от -Wuninitialized : warning: ‘name’ is used uninitialized in this function [-Wuninitialized]

Ответ №1:

Включите оптимизацию компилятора. Довольно много компиляторов по умолчанию почти отключают оптимизацию, так как они компилируют каждый оператор независимо. В таком рабочем режиме они не могут определить, неинициализирован ли указатель. Это упрощает отладку в целом, потому что один шаг, проверка и изменение работают так, как вы ожидаете, но за это приходится платить. Если вы не поймаете его раньше, вы поймаете его при компиляции с включенной оптимизацией.

Также включите предупреждения компилятора, пока вы этим занимаетесь. Обычно вы хотите -Wall .

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

Ответ №2:

Вам нужно использовать -Wall -Wextra вместо только -Wall для получения «разумных» предупреждений в GCC

  • -Wextra
    • Это включает некоторые дополнительные флаги предупреждения, которые не включены -Wall . (Раньше вызывалась эта опция -W . Старое имя по-прежнему поддерживается, но новое имя является более описательным.)
      • -Wuninitialized

https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html