Хорошие подсказки, простые ошибки
Ой! Что-то случилось. Моя программа "свалилась", напечатала какой-то мусор или, кажется, "зависла". Что мне делать?
Начинающие обычно винят в происшедшем компилятор, библиотеку или еще что-нибудь, но только не свой код. Опытные программисты были бы счастливы сделать то же самое, но они-то знают, что проблема, скорее всего, заключается в их собственной ошибке.
К счастью, в большинстве своем ошибки просты, и их можно обнаружить с помощью простых приемов. Изучите улики – неверные результаты работы и попытайтесь догадаться, как такие результаты могли возникнуть. Посмотрите на отладочную выдачу перед аварийным завершением; если возможно, получите у отладчика стек вызовов. Теперь вы уже кое-что знаете о том, что именно произошло и где.
Остановитесь, подумайте. Как такое могло случиться? Рассуждайте, исходя из состояния "свалившейся" программы, чтобы определить причину.
Процесс отладки включает в себя обратную трассировку (backward reasoning) – прослеживание событий в обратном порядке, как в детективе. Случилось что-то невозможное, и единственное, что известно точно, – невозможное случилось. Для того чтобы раскрыть причины, нужно мысленно проходить обратный путь от результата к возможной причине. Когда у нас имеется полное объяснение, мы знаем, что именно исправлять и, по ходу дела, скорее всего, обнаружим несколько других вещей, которых мы не ожидали.
Ищите знакомые ситуации.
Спросите себя, известна ли уже вам эта ситуация. "Я уже видел это" – с этой фразы часто начинается понимание, а иногда даже и возникает ответ. Обычные ошибки имеют четко различимые признаки. Например, начинающие программисты на С часто пишут:
? int n
Вместо:
int n; scant ("$ &n);
При такой попытке ввода значения обычно возникает ошибка обращения за пределы доступной памяти. Преподаватели языка С немедленно узнают этот симптом.
Несовпадающие типы и преобразования при вызове printf и scant рождают бесконечный поток тривиальных ошибок:
Признаком этой ошибки иногда бывают абсурдные значения переменных: огромные целые, невероятно большие или невероятно маленькие значения с плавающей точкой. На Sun SPARC эта программа выводит огромное целое и астрономическое число с плавающей точкой (выдача отформатирована, чтобы не выходить за поля страницы):
Другой обычной ошибкой является использование %f вместо %lf, когда значение типа double читается с помощью scanf. Некоторые компиляторы ловят такие ошибки, проверяя, соответствуют ли типы аргументов scanf и printf параметрам форматной строки; если вывод всех предупреждений компилятора разрешен, то относительно приведенного выше обращения к printf компилятор GNU gcc сообщит:
х.с:9: warning: int format, double arg (arg 2) x.c:9: warning: double format, different type arg (arg 3)