#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