2010-05-12 3 views
4

Могут ли семантические ошибки быть обнаружены компилятором или нет? Если нет, когда обнаружены ошибки?Семантические ошибки

Насколько я знаю, семантические ошибки - это те ошибки, которые возникают из выражений операторов с неправильным числом/типом операндов.

Например:

n3=n1*n2;//n1 is integer, n2 is a string, n3 is an integer 

Данное заявление семантически некорректен.

Но при чтении C Primer Plus Стивен Прата я нашел следующее заявление

компилятор не обнаруживает смысловые ошибки, потому что они не нарушают правила C. У компилятора нет возможности угадать ваши истинные намерения. Это оставляет вам возможность найти такие ошибки. Один из способов - сравнить то, что программа делает с тем, что вы ожидали от нее.

Если не компилятор, который обнаруживает эти ошибки?

Я что-то не хватает?

+0

Ваш пример не является семантической ошибкой - это синтаксическая ошибка. Даже если строка * int действительна (это может означать повторную строку n раз), типы несовместимы. – Bevan

+0

@Bevan, термины иногда могут использоваться по-разному, и «семантическая ошибка» кажется одной из них. Я определенно назвал бы это семантической ошибкой, и я определенно не назвал бы это синтаксической ошибкой. (См. Мой комментарий к отвечу Майкла ниже.) –

+0

@ Томас. Я вижу (и уступаю) вашу мысль. Я использовал термин «семантический» в духе цитаты OP от Стивена Прата. – Bevan

ответ

5

Слово «семантика» неоднозначно, и вы столкнулись с двумя слегка отличающимися значениями в этих разных контекстах.

Первое значение (ваш код) связано с тем, как компилятор интерпретирует введенный вами код. Но для этого есть различная степень интерпретации - синтаксис - это один уровень, где интерпретация просто решает, что n1*n2 означает, что вы хотите выполнить умножение. Но здесь также существует более высокий уровень интерпретации - если n1 является целым числом, а n2 является плавающей точкой, каков результат? Что, если я брошу его, если он будет округлен, усечен и т. Д.?Это «семантические» вопросы, а не синтаксические, но кто-то где-то решил, что да, компилятор может ответить на эти вопросы большинству людей.

Они также решили, что у компилятора есть ограничения на то, что он может (и должен!) Интерпретировать. Например, он может решить, что кастинг на int является усечением, а не округлением, но он не может решить, что вы действительно хотите, когда пытаетесь умножить массив на число.

(Иногда люди решают, что они могут, хотя. В Python [1] * 3 == [1,1,1].)

Второе значение относится к гораздо более широкой области. Если предполагается, что результат этой операции будет отправлен на периферийное устройство, которое может принимать значения от 0x000 до 0xFFF, и вы умножаете 0x7FF на 0x010, очевидно, что вы сделали семантическую ошибку. Разработчики периферийного устройства должны решить, справляться ли с этим или каким образом. Вы, как программист, можете также принять меры по проверке здравомыслия. Но компилятор понятия не имеет об этих внешних семантических ограничениях или о том, как их принудительно применять (отфильтровать ввод пользователя? Вернуть ошибку? Truncate? Wrap?), О чем говорит вторая цитата.

5

«Семантическая ошибка» - еще один термин для «логической ошибки», где вы буквально пишете неправильный код. Например, написание n3=n1*n2, когда вы действительно хотели разделить - компилятор не может сказать, что ваш алгоритм должен делиться, а не умножать; вы сказали ему размножаться, так оно и есть.

Ошибки вы описали в вашем примере ошибка безопасности типа и компиляторы могут поймать, что во время фазы проверки типов (если язык сильно типизированные)

+2

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

+0

@ Томас Это объясняет, где ФП слышал это; этот термин, по-видимому, используется по-разному, поскольку [Википедия определяет] (http://en.wikipedia.org/wiki/Semantic_error) так, как я сказал –

1

семантических ошибок все те, где ваш код делает то, что вы не намеревался.

Эти ошибки могут быть обнаружены путем тестирования или анализа.

Анализ означает, что вы или инструмент просматриваете свой код и пытаетесь выяснить проблемы. Это включает использование обзоров кода и статических анализаторов.

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

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

0

На самом деле, умножая строку и целое числом является синтаксической ошибкой, так как умножение несовместимых типов (таких как строки и целого число) не определен в С.

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

0

Эта цитата говорит о вещах вроде x <= 1, где вы действительно должны были сделать x < 1.

Но для семантики языка (не допускается добавить строку и целое число), да, это компилятор, который обрабатывает это.

0

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

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

0

Если не компилятор, который обнаруживает эти ошибки?

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

Иногда среда выполнения: программа обращается к недопустимому адресу из-за ошибки и находится вне адресного пространства, доступного для процесса.

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

1

Я думаю, что писатель, который написал книгу, по-разному определял «семантический». Для большинства компиляторов есть шаг с участием semantic checks.

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

-1

На самом деле (как нет string типа в C, но только char*), вы можете очень хорошо размножаются n1 с n2. Операция является законной и четко определена, поэтому компилятор не выдаст ошибку.

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

+0

GCC отказывается компилировать '' 123 '* 3'. – detly

0

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

2

В основном существует три типа ошибок.

1) Синтаксические ошибки. Это недопустимый код, который компилятор не понимает, например. ваш пример умножения строки с целым числом в C. Компилятор будет обнаружить их, потому что он не может их скомпилировать.

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

Существует третий класс, который может быть самым дорогим:

3) ошибки дизайна. Код правильный и без ошибок и делает именно то, что вы намеревались. Но ваши намерения ошибочны, например. основанные на неправильных предположениях, неправильных моделях, или вы использовали неправильные формы, неправильно поняли клиента или тому подобное.

+0

Действительно, есть три типа ошибок, а не четыре или пять? Как это удивительно, как «аргумент триллема Джоша Макдауэлла». Слабый соус. Рассмотрим: ошибки времени выполнения, такие как Ctrl-C или SIGPWR. Да, не ожидая, что каждая ошибка времени выполнения может быть сосредоточена под «семантикой» или «дизайном», но сами ошибки времени выполнения, только причина для такой классификации - поддерживать ваш чрезмерно напористый ответ. Также имеются ошибки в документации. –

Смежные вопросы