Начинающие программисты разочарованы отсутствием глоссария ошибок компилятора

65

Друг моей семьи попросил меня немного помочь, когда он учится программировать (на языке Си). Пока мы говорили, он выразил разочарование по поводу того, что ему трудно понять сообщения об ошибках, которые его компилятор (GCC) выдает ему, когда он делает ошибки. Он не понимает всех используемых терминов, и иногда это их комбинация, которая находится за пределами его понимания. Он спрашивал меня: «Почему документация компилятора не содержит более подробных объяснений сообщений об ошибках?» - и у меня не было хорошего ответа для него.

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

Итак, как начинающему программисту подойти к проблеме понимания сообщений об ошибках компилятора? Конкретно с комбинацией С и GCC?

einpoklum - восстановить Монику
источник
7
«Итак, как начинающему программисту подойти к пониманию сообщений об ошибках компилятора?» / sarcasm Первый навык, необходимый для того, чтобы уметь читать каждый бит из сообщения компилятора, в том числе связывать его с самим контекстом. / сарказм выключен. Это редко оказывается ошибкой или ошибкой в ​​компиляторе.
πάντα ῥεῖ
10
@MasonWheeler: новичок часто не выбирает, какой компилятор использовать при прохождении обучения. И GCC является общим знаменателем многих, многих систем ...
einpoklum - восстановить Монику
25
Когда дело доходит до ошибок шаблона GCC C ++, я нахожу, что если я прекращаю читать после «Ошибка <file: line>» и изучаю исходные файлы, я нахожу ошибку быстрее, с дополнительным побочным эффектом поддержания моего здравомыслия, чем если я прочитал фактическую ошибку, данную GCC .....
Mattnz
19
Решение очевидно: используйте компилятор с менее запутанным выводом. Я предлагаю rmcc . Он печатает Yes.или No.зависит от того, скомпилирован ли ваш код или нет. Мгновенно убирает разочарование от непонимания длинных и бессмысленных сообщений!
труба
21
С не очень хороший язык для начинающих - и вы наткнулись на одну из причин. Тем не менее, Clang имеет тенденцию предлагать гораздо лучшие ошибки, которые также могут быть более привлекательными для начинающих.
Теодорос Чатзигианнакис

Ответы:

163

Несколько полезных приемов:

  • Включите -Wallи -Werror. Может показаться нелогичным, когда вы боретесь с расшифровкой сообщений об ошибках, чтобы создать еще больше сообщений об ошибках, но предупреждения обычно легче понять и приблизить к фактическому источнику проблемы, а их игнорирование может привести к ошибкам, которые трудно понять. ,
  • Просто попробуйте исправить первую ошибку в списке. Часто ошибки сочетаются друг с другом, что приводит к тому, что последующие сообщения об ошибках не являются настоящими ошибками. Исправьте один и перекомпилируйте. Вы будете лучше исправлять несколько сообщений об ошибках, когда приобретете больше опыта.
  • Используйте новейшую возможную версию компилятора. С - чрезвычайно стабильный язык. Поэтому огромная часть улучшений в новых компиляторах заключается не в добавлении языковых функций, а в улучшении работы разработчика, в том числе улучшении сообщений об ошибках. Многие широко используемые дистрибутивы Linux по умолчанию имеют очень старые версии gcc.
  • Программа пошаговая. Не пытайтесь написать тонну кода перед компиляцией. Напишите минимально возможную сумму, которая все еще будет компилироваться. Если вы изменили только одну строку с момента последней компиляции, гораздо проще определить, какая строка содержит реальную проблему.
  • Напишите юнит-тесты. Это делает вас более уверенным, чтобы внести ясность в изменения рефакторинга при исправлении ошибок компиляции.
Карл Билефельдт
источник
23
Хорошая IDE также может очень помочь, например. Подчеркивая ошибки красным цветом.
BlueRaja - Дэнни Пфлугхофт
86
"Программируйте пошагово. Не пытайтесь писать тонну кода перед компиляцией. Напишите минимально возможное количество, которое все равно будет компилироваться. Если вы изменили только одну строку с момента последней компиляции, это намного проще выяснить какая строка содержит актуальную проблему. " Это, так много, это. Также большинство IDE предупредит вас, если вы напишете код, который не будет компилироваться, и выделит ошибки.
Полигном
4
@einpoklum: не стоит недооценивать третий вариант; сообщения об ошибках компилятора значительно улучшились. Аналогичным образом, используйте несколько компиляторов (например, gcc и clang) - ловит больше ошибок / предупреждений, и один из них может иметь лучшую диагностику для конкретной проблемы, чем другой.
Мат
19
@einpoklum: писать вещи постепенно, очень удобно , особенно для начинающих. Черт возьми, если вы считаете, что «короткие задания по программированию» не могут выполняться постепенно, разделив их на несколько небольших функций, реализовав и скомпилировав их один за другим, вы должны попытаться улучшить этот навык для себя…
Док Браун,
4
Трюк, который мне помог: если в сообщении об ошибке упоминается строка N, отметьте строку N-1. Например, если вы пропустили точку с запятой в строке 17, в сообщении об ошибке будет указано, что что-то не так со строкой 18. Это происходит потому, что компилятор ожидал точку с запятой, но вместо этого получил что-то еще, на следующей строке.
user2023861
56

Твой друг не нуждается в глоссарии. Глоссарий ему не поможет. Что ему нужно, так это лучшее понимание того, что делать при возникновении ошибок компилятора.

Ошибки компилятора C не так интуитивны, как, скажем, ошибки компилятора C #, по многим причинам, главным образом связанным с природой языка «близко к металлу». Устранение ошибок компилятора в C не является упражнением в сопоставлении с образцом, поскольку получение может не иметь ничего общего с реальной проблемой. В отличие от C # или Java, где сообщение об ошибке обычно отображается в точном месте кода и проблемы, ошибки в C, вероятно, будут многочисленными и далеко.

Примером этого является «ожидаемая точка с запятой» или любое количество синтаксических ошибок, которые указывают на то, что синтаксический анализатор зависает на чем-то (не обязательно точка с запятой). Или что-то вроде «неожиданного форвардного объявления», ошибка, которая, когда я ее вижу, неизменно означает, что в одном из моих файлов .h произошла неправильная прописная буква, но не указывает на файл .h как на источник проблемы.

Стратегия вашего друга не должна состоять в том, чтобы сопоставить это со списком ошибок и решений; она должна быть , чтобы понять синтаксис и спецификации языка C достаточно хорошо , чтобы понять, что текущая проблема.

Роберт Харви
источник
17
Нет. Идея состоит в том, чтобы знать язык достаточно хорошо, чтобы знать, что вы не можете делать присваивания числовому выражению, но только переменной. Вам не нужно знать, что такое lvalue, поэтому они не учат этому на курсах для начинающих.
Роберт Харви
18
По сути, да. Но практически это невозможно. Я делал это в течение очень долгого времени, и я все еще получаю непонятные сообщения об ошибках компилятора каждый раз, когда пишу программу на Си. Однако я редко пытаюсь прочитать эти сообщения и попытаться понять их; вместо этого я смотрю на то, куда указывает сообщение об ошибке, и, поскольку я знаю, как должна выглядеть базовая синтаксическая структура программы на C, я могу относительно быстро обнаружить проблему, не тратя время на расшифровку сообщений об ошибках.
Роберт Харви
36
Иными словами, запрос глоссария для понимания ошибок компилятора немного напоминает чтение словаря для понимания английского языка; это не совсем так, как это работает. Вы изучаете и понимаете английский, читая и записывая его, а не читая словарь.
Роберт Харви
14
[пожимает плечами] Если вы не используете словарь, чтобы просто дополнить уже существующее знание английского языка, я бы сказал, что вы делаете это неправильно. Последнее, что я хотел бы предложить, это то, что заставляет начинающих программистов зацикливаться на словаре больше, чем они уже есть. Программистам не нужно больше слов; им нужно больше навыков.
Роберт Харви
13
@einpoklum, глоссарий здесь не поможет. Описание слова «lvalue», вероятно, будет либо слишком техническим для начинающего, либо в духе «того, что может быть в левой части задания», что столь же бесполезно.
Барт ван Инген Шенау
26

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

Это особенно верно для самых сложных типов ошибок. Например, когда вы смешиваете две одинаковые конструкции (что весьма необычно для начинающих), компиляторы обычно имеют проблему при создании правильного сообщения об ошибке. Это может привести к путанице, когда компилятор выдает сообщение об ошибке о неправильном использовании конструкции A, когда вы фактически намеревались создать конструкцию B. Второй компилятор может сделать вывод, что вы намеревались B.

MSalters
источник
13

Кто- то недавно пытался создать глоссарий об ошибках GCC в Wikibooks , но похоже, что он никогда не работал и не обновлялся.

Раздел «Ошибки» гораздо дальше, чем раздел «Предупреждения». Похоже, что он был нацелен на G ++, но там все еще есть некоторая полезная информация для вашего друга.

nBurn
источник
12

В дополнение к приведенным выше ответам, обратите внимание, что большинство компиляторов не имеют полных глоссариев ошибок - их было бы много, чтобы поддерживать, так как сами сообщения часто меняются, и их довольно много.

Лучшая замена глоссария - доступ к Интернету. Всякий раз, когда компилятор выдает ошибку, которую вы не понимаете, успокойтесь, что маловероятно, что вы первыми столкнулись с ней и были сбиты с толку. Быстрого Google точного сообщения часто достаточно, чтобы предоставить вам много информации в удобном для чтения формате, часто с примером кода, очень похожим на ваш собственный.

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

Dúthomhas
источник
1
Я не думаю, что это будет много работы для поддержания. Кроме того, он может быть добавлен публикой, например, Stackoverflow или Wiki, с доверенными людьми, которым предоставлены разрешения редактора.
einpoklum - восстановить Монику
6
@einpoklum Вы когда-нибудь видели документацию по PHP? Вот что происходит, когда вы позволяете сообществу позаботиться об этом.
Кевин
4
Когда-то изданные (печатные) руководства были единственным доступным ресурсом. Они обычно были достаточно хорошо написаны, чтобы предоставить необходимую информацию / руководство для решения проблемы. С развитием Интернета никто больше не публикует в печатном виде (если вообще, это онлайн). Качество «официального» справочного материала (онлайн или иным способом) значительно упало за десятилетия, которые я программировал, поэтому самым лучшим доступным ресурсом часто является Google, а наиболее полезные результаты часто появляются в Stackoverflow.
Zenilogix
2
Даже если глоссарий действительно существует, поисковые системы могут быть лучшим способом доступа к ним. Они также полезны для обнаружения, когда вы находитесь на неизведанной территории: когда единственным результатом поиска является исходный код, определяющий сообщение об ошибке;)
Warbo
2
В колледже однажды я получил ошибку компилятора: «Дэйв не думает, что это должно произойти. Пожалуйста, напишите ему по адресу <dave@example.com>». Я написал ему по электронной почте, и фактически я был первым, кто совершил эту ошибку!
user1118321
6

Стандарт C использует ряд терминов, таких как «lvalue» и «объект», в отличие от других языков программирования, и сообщения компилятора часто пишутся в таких терминах. Использование терминологии является непоследовательным в некоторых частях Стандарта, но любой, кто хочет изучать C, должен посмотреть проекты стандартов C89, C99 и / или C11, а также обоснование документов для них. Поиск, например, «черновик C99» или «обоснование C89», должен работать очень хорошо, хотя вам может потребоваться убедиться, что вы получили ожидаемый документ. Хотя большинство компиляторов поддерживают стандарт C99, может быть полезно узнать, чем он отличается от стандарта C89, и обоснование C89 может предложить некоторые исторические предпосылки, которых нет в более поздних версиях.

Supercat
источник
11
Стандарт C - это очень плотный и тяжелый текст. У новичка нет шансов понять это.
NieDzejkob
4
@NieDzejkob: терминология, используемая компиляторами - которая, кажется, является тем, о чем идет речь - основана на стандарте. Хотя вы правы, что части Стандарта непостижимы (отчасти потому, что он разработан комитетом, и авторы, похоже, не имеют последовательного понимания того, что его части должны означать), но любой, кто хочет понять, что такие термины, как «lvalue» означают, должны знать, откуда они пришли. Кроме того, если кто-то хочет понять, почему что-то вроде этого x=0x1e-xприводит к ошибке, я действительно не знаю ничего, кроме Стандарта ...
суперкат
3
Я согласен с @NieDzejkob: стандарт C - это не тот текст, с которым вы хотите столкнуться с новичком. Новички нуждаются в положительном практическом опыте быстро . И они должны изучать новые вещи один за другим, когда они появляются. Чтение стандарта или логического обоснования занимает слишком много времени при полной перегрузке новичка информацией.
Cmaster
2
@cmaster: Я начал с C89 Standard много лет назад, и это было неплохо даже в те дни, когда браузеры имели удобную функцию «найти текст». Я признаю, что более поздние стандарты становились все хуже и хуже. Хотя никто не должен полагаться на Стандарт в качестве единственной ссылки, важно признать расхождение между народной мудростью о том, как ведут себя компиляторы микрокомпьютеров, и способами, которыми Стандарт позволяет вести себя некачественным поведением, поэтому каждый будет готов, если у него есть иметь дело с последним.
суперкат
3
@cmaster: В любом случае, кто-то, кто программирует C, должен знать о Стандарте и знать, как с ним обращаться, когда это необходимо, даже если он не собирается пытаться прочитать все целиком. Например, если кто-то выполняет веб-поиск стандартной библиотечной функции, он может найти ссылку, которая описывает поведение одной реализации в некоторых угловых случаях, не упоминая, что с точки зрения Стандарта эти угловые случаи вызывают неопределенное поведение, а другие реализации могут не работает так же. Если вместо этого искать Стандарт, можно избежать этой проблемы.
суперкат
5

Я удивлен, что никто не дал очевидного ответа и, я подозреваю, тот, который чаще всего используется на практике: просто не читайте сообщения об ошибках.

Подавляющее большинство значения большинства сообщений об ошибках заключается просто в том, что что-то не так в такой-то строке. Большую часть времени я просто смотрю на номер строки и иду к этой строке. Мое «прочтение» сообщения об ошибке в тот момент - это обычно то, что попалось мне на глаза, даже не просмотр. Если не сразу понятно, что не так на линии или рядом с ней, тогда я прочитаю сообщение. Этот рабочий процесс еще лучше с IDE или инструментами, которые подсвечивают ошибки на месте и автоматически выполняют предложение Карла Билефельдта, чтобы рассматривать только небольшие изменения.

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

С одной стороны, большинство ошибок, которые может совершить новичок, вероятно, будут болезненно очевидны для опытного программиста без помощи компилятора. С другой стороны, они гораздо менее очевидны для новичка (хотя многие будут очевидны, большинство ошибок - глупые ошибки). На данный момент я полностью согласен с Робертом Харви, новичку просто нужно лучше познакомиться с языком. Нельзя избежать этого. Ошибки компиляции, которые ссылаются на незнакомые концепции или кажутся удивительными, должны рассматриваться как побуждения углубить знание языка. Аналогично для случаев, когда компилятор жалуется, но вы не можете понять, почему код неправильный.

Опять же, я согласен с Робертом Харви, что необходима лучшая стратегия для использования ошибок компилятора. Я изложил некоторые аспекты выше, а ответ Роберта Харви дает другие аспекты. Даже не ясно, что ваш друг надеется сделать с таким «глоссарием», и очень маловероятно, что такой «глоссарий» будет действительно полезным для вашего друга. Сообщения компилятора, конечно, не место для введения в понятия языка 1, и «глоссарий» не так уж и лучше для этого. Даже с ясным описанием того, что означает сообщение об ошибке, он не скажет вам, как решить проблему.

1 Несколько языков, таких как Elm и Dhall (и, возможно, Racket), а также несколько «ориентированных на новичка» реализаций языков пытаются это сделать. В этом ключе совет MSalters использовать другую реализацию имеет прямое отношение. Я лично нахожу такие вещи неубедительными и не совсем нацеленными на правильную проблему. Это не значит, что нет способов улучшить сообщения об ошибках, но, как мне кажется, они вращаются вокруг того, чтобы сделать верования компилятора и основы этих верований более ясными.

Дерек Элкинс
источник
4

Итак, как начинающему программисту подойти к проблеме понимания сообщений об ошибках компилятора? Конкретно с комбинацией С и GCC?

Попросите вашего друга сделать следующее при обнаружении ошибки, которую он не понимает:

  • Удалить / прокомментировать код, добавленный с момента последней успешной сборки.
  • Положите его обратно и скомпилируйте
  • Повторяйте, пока не произойдет ошибка

Ошибки компилятора говорят только о том, что компилятор не понимает в вашем коде, а не о том, что с ним не так. Этот подход занимает примерно столько же времени, что и поиск ошибок в Google и чтение некоторых документов или сообщения StackOverflow, но дает гораздо лучшее понимание того, что вы делаете неправильно.

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

Наконец, скажите им, чтобы они работали над одной вещью одновременно, не работайте с несколькими файлами без промежуточной компиляции, не вводите несколько зависимостей одновременно и т. Д.

Kevin
источник
4

Другим способом было бы, чтобы друг написал свой собственный глоссарий с течением времени, когда он сталкивается с различными сообщениями об ошибках. Часто лучший способ чему-то научиться - это научить этому. Конечно, к тому времени, когда глоссарий будет готов, он, вероятно, больше не понадобится.

Мой личный опыт работы с GCC заключается в том, что каждое сообщение об ошибке относится к «обычному» набору ошибок. Например, когда GCC говорит: «Вы забыли &», это обычно означает, что я забыл скобки. Конечно, какие ошибки соответствуют тому, какие сообщения об ошибках будут зависеть от программиста, это еще одна веская причина для друга написать свой собственный глоссарий.

Оуэн
источник
1
Этот документ имеет чрезвычайно важное дополнительное преимущество: его можно разместить в Интернете (даже если в нем всего 5-10 записей), и он станет отличным отличием при подаче заявления на стажировку.
Джош Рамбут