Значимые диагностические сообщения - PullRequest
4 голосов
/ 18 августа 2010

Просматривая несколько постов, я чувствую, что многие вопросы возникают из-за того, что компиляторы / реализации не выдают очень значимое сообщение много раз (но не всегда).Это особенно верно в случае шаблонов, где сообщения об ошибках могут быть как минимум очень пугающими.Рассматриваемый случай может быть темой обсуждения

Поэтому я хотел бы понять несколько вещей:

a) Почему это таккомпиляторы иногда не могут выдавать более значимые / полезные сообщения об ошибках?Это причина чисто практическая или техническая или есть что-то еще.(У меня нет опыта работы с компилятором)

b) Почему они не могут дать ссылку на самый соответствующий соответствующий C ++ Стандартный стих / раздел, поэтомучто сообщество разработчиков может лучше изучить C ++?

РЕДАКТИРОВАТЬ:

Обратитесь к теме здесь для другого примера.

РЕДАКТИРОВАТЬ:

Обратитесь к теме здесь для другого примера.

Ответы [ 6 ]

4 голосов
/ 22 августа 2010

Основная проблема заключается в том, что диагностика компилятора имеет дело с вещами, которые вы не написали .

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

Если вы пропустите точку с запятой, компилятор, очевидно, нигде не увидит эту точку с запятой. Конечно, одна из вещей, которые он может сделать, это угадать: «Может быть, пользователь пропустил точку с запятой. В конце концов, это распространенная ошибка». Но где должна быть эта точка с запятой? Поскольку вы допустили ошибку, код не может быть проанализирован в синтаксическом дереве, поэтому нет четкого индикатора, что «этот узел отсутствует в дереве». И может быть более одного места, где точка с запятой может быть вставлена ​​так, чтобы окружающий код был правильно проанализирован. И более того, сколько кода вы собираетесь попытаться проанализировать / перекомпилировать, как только обнаружите, в чем может быть ошибка? Компилятор может вставить точку с запятой, но, по крайней мере, он должен перезапустить анализ этого блока кода. Но, возможно, это привело к ошибкам в коде. Так что, возможно, следует перекомпилировать всю программу, просто чтобы убедиться, что исправление, предложенное компилятором, было действительно правильным. Но вряд ли это вариант. Это занимает слишком много времени.

Скажем, у вас есть такой код:

struct foo {
 ...
}

void bar();

в чем здесь ошибка? Глядя на это, мы с тобой скажем: «Тебе не хватает точки с запятой после определения класса». Но как компилятор может сказать? void может быть опечаткой. Возможно, вы действительно намеревались написать имя экземпляра типа foo. тогда настоящая ошибка заключается в том, что за этим следует то, что сейчас выглядит как вызов функции.

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

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

Поэтому иногда может быть лучше вывести короткое, краткое сообщение, в котором говорится только то, в чем мы уверены (скажем, что за определением класса не может следовать имя типа). Это не так полезно, как сказать «вы пропустили точку с запятой после определения класса», но это менее вредно, если компилятор угадает неправильно.

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

Написание хороших ошибок компилятора нелегко, особенно на таком грязном языке, как C ++. Но когда это сказано, некоторые компиляторы (включая MSVC и GCC) могут быть намного лучше. Я считаю, что лучшая диагностика компилятора - одна из основных целей Clang.

3 голосов
/ 18 августа 2010

Распространенная ошибка, которую люди совершают, пытаясь создать что-то абсолютно надежное, заключается в недооценке изобретательности полных глупцов.--- Дуглас Адамс

Я попытаюсь объяснить некоторые обоснования диагностики (как их называет стандарт):

a) ПочемуНеужели компиляторы иногда не могут выдавать более значимые / полезные сообщения об ошибках?

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

b) Почему они не могут дать ссылку на наиболее соответствующий соответствующий стандарт / раздел C ++, чтобы сообщество разработчиков могло лучше изучить C ++?

  • Не у всех есть копия стандарта.

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

  • Кроме того, не все компиляторы соответствуют стандартам.Грустно, но факт.

  • Некоторые компиляторы реализуют более одного стандарта.Вы действительно ожидаете, что они процитируют тексты стандартов C & V из 3-х за простую ошибку «отсутствует ;»?

  • Наконец, стандарт является кратким и менее читабельным, чем хотелось бы комитету (хорошо, это замечание насмешливо, но довольно точно отражает положение дел!)

И еще раз прочитайте цитату сверху;)

PS: Что касается шаблонных сообщений об ошибках, я должен предложить следующее:

  • Для немедленного облегчения используйте STLFilt
  • Молитесь, чтобы Концепции вошли в следующий стандарт
2 голосов
/ 18 августа 2010

Некоторые компиляторы лучше других. Компилятор из comeau, который я слышал, дает гораздо более приятные ошибки. Вы можете попробовать это в http://www.comeaucomputing.com/tryitout/

1 голос
/ 18 августа 2010

Фактор, не упомянутый в других ответах, которые я прочитал: компиляторы C ++ выполняют очень сложную работу, и не усложняют ее, классифицируя код, который они компилируют, в «ожидаемый» материал и «неожиданный» , Например, мы, как программисты, понимаем, что std :: string - это конкретная реализация std :: basic_string с различными типами символов, чертами, распределителями - что угодно. Итак, когда есть ошибка, мы просто хотим знать, что она включает в себя строку, а не видеть все остальное. Но, скажем, нас попросили отладить сообщение об ошибке, с которым столкнулся клиент при использовании нашей библиотеки. Возможно, нам нужно точно увидеть, как был создан экземпляр шаблона, чтобы увидеть, в чем проблема, и просто увидеть некий typedef, который находится внутри их кода - к которому мы, возможно, даже не имеем доступа - сделает сообщения об ошибках бесполезными. Итак, программисты на разных уровнях в программном стеке хотят видеть разные вещи, и большинство компиляторов не хотят верить в это или разрешать индивидуальные настройки, они просто выплевывают все и верят, что программист быстро научится фокусироваться на вещи на уровне, который им нужен. В большинстве случаев программисты быстро учатся это делать, но иногда это сложнее, чем другим.

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

Ура, Tony

1 голос
/ 18 августа 2010

ИМХО, чаще всего важен не текст сообщения, а умение связать его с источником. Компилятор C ++ в VS2005, кажется, показывает сообщения об ошибках, указывающие файл, в котором произошла ошибка, но не файл, из которого она была включена. Это может быть настоящей болью, например, когда ошибка в одном заголовочном файле приводит к ошибкам компиляции в следующем. Также может быть трудно определить, что происходит с макросами препроцессора.

1 голос
/ 18 августа 2010

Авторы компилятора не выбраны из-за их английских способностей и не выбирают свою работу из-за возможностей написания.

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

Ссылка на правила стандарта по разрешению перегрузки может быть даже контрпродуктивной в этом случае. Чтобы решить проблему, я найду нужного кандидата и сравню его с сайтом вызовов. В 99% случаев я хочу простой матч без излишеств, а 99% сложного механизма разрешения не будут применяться. Необходимость пересмотреть правила разрешения в стандарте часто указывает на то, что вы попадаете в глубокую ду-ду.

Я думаю, что лишь малая часть программистов действительно склонна или полностью способна ориентироваться и интерпретировать стандарт ISO.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...