Семантические ошибки - PullRequest
6 голосов
/ 12 мая 2010

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

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

Например:

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

Вышеприведенное утверждение семантически неверно.

Но, читая «С Primer Plus» Стивена Прата, я нашел следующее утверждение

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

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

Я что-то упустил?

Ответы [ 11 ]

5 голосов
/ 12 мая 2010

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

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

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

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

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

5 голосов
/ 12 мая 2010

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

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

2 голосов
/ 12 мая 2010

Есть в основном три типа ошибок.

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

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

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

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

1 голос
/ 12 мая 2010

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

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

1 голос
/ 12 мая 2010

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

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

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

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

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

0 голосов
/ 12 мая 2010

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

0 голосов
/ 12 мая 2010

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

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

0 голосов
/ 12 мая 2010

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

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

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

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

0 голосов
/ 12 мая 2010

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

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

0 голосов
/ 12 мая 2010

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

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

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