Это ваша первая программа на C (или C++) — она не такая уж большая, и вы собираетесь скомпилировать ее. Вы нажимаете на compile
(или вводите команду компиляции) и ждете. Ваш компилятор выдает пятьдесят строк текста. Вы выбираете слова warning
и error
. Задумываетесь, значит ли это, что все в порядке. Вы ищите полученный исполняемый файл. Ничего. Черт возьми, думаете вы, я должен выяснить, что все это значит …
Типы ошибок компиляции
Во-первых, давайте различать типы ошибок. Большинство компиляторов покажет три типа предупреждений во время компиляции:
- предупреждения компилятора;
- ошибки компилятора;
- ошибки компоновщика.
Хоть вы и не хотите игнорировать их, предупреждения компилятора не являются чем-то достаточно серьезным, чтобы не скомпилировать вашу программу. Прочитайте следующую статью, которая расскажет вам, почему стоит дружить с компилятором и его предупреждениями. Как правило, предупреждения компилятора — это признак того, что что-то может пойти не так во время выполнения. Как компилятор узнает об этом? Вы, должно быть делали типичные ошибки, о которых компилятор знает. Типичный пример — использование оператора присваивания
=
вместо оператора равенства ==
внутри выражения. Ваш компилятор также может предупредить вас об использовании переменных, которые не были инициализированы и других подобных ошибках. Как правило, вы можете установить уровень предупреждений вашего компилятора — я устанавливаю его на самый высокий уровень, так что предупреждения компилятора не превращаются в ошибки в выполняемой программе (“ошибки выполнения”).
Тем не менее, предупреждения компилятора не должны останавливать работу вашей программы (если только вы не укажете компилятору рассматривать предупреждения как ошибки), так что они, вероятно, не так серьезны как ошибки.
Ошибки — это условия, которые препятствуют завершению компиляции ваших файлов.
Ошибки компилятора ограничены отдельными файлами исходного кода и являются результатом “синтаксических ошибок”. На самом деле, это означает, что вы сделали что-то, что компилятор не может понять. Например, выражение for(;)
синтаксически не правильно, потому что цикл всегда должен иметь три части. Хотя компилятор ожидал точку с запятой, он мог также ожидать условное выражение, поэтому сообщение об ошибке, которое вы получите может быть что-то вроде:
line 13, unexpected parenthesis ‘)’
Заметьте, что ошибки компилятора всегда будут включать номер строки, в которой была обнаружена ошибка.
Даже если вы прошли процесс компиляции успешно, вы можете столкнуться с ошибками компоновщика. Ошибки компоновщика, в отличие от ошибок компилятора, не имеют ничего общего с неправильным синтаксисом. Вместо этого, ошибки компоновщика — это, как правило, проблемы с поиском определения функций, структур, классов или глобальных переменных, которые были объявлены, но не определены, в файле исходного кода. Как правило, эти ошибки будут иметь вид:
could not find definition for X
Как правило, процесс компиляции начинается с серии ошибок компиляции и предупреждений и, исправив их, вы столкнетесь с ошибками компоновщика. В свою очередь, я бы сначала исправлял ошибки компиляции, а затем ошибки компоновщика.
Ошибки компилятора — с чего начать?
Если вы столкнулись с перечнем пятидесяти или шестидесяти ошибок и предупреждений, то будет сложно определить с чего начать. Самое лучшее место, тем не менее, в начале списка. В самом деле, вы почти никогда не начинаете исправлять ошибки от конца файла до его начала по одной простой причине: вы не знаете ошибки ли они на самом деле!
Одна ошибка в верхней части вашей программы может вызвать целый ряд других ошибок компилятора, потому что эти строки могут рассчитывать на что-то в начале программы, что компилятор не смог понять. Например, если вы объявляете переменную с неправильным синтаксисом, компилятор сообщит о синтаксических ошибках, и что он не может найти объявление для переменной. Точка с запятой, поставленные не в том месте, могут привести к огромному количеству ошибок. Это происходит, потому что синтаксис C и C++ синтаксис позволяет объявить тип сразу же после его определения:
struct { int x; int y; } myStruct;
код создаст переменную, MyStruct
, с местом для хранения структуры, содержащей два целых числа. К сожалению, это означает, что если вы опустите точку с запятой, компилятор будет интерпретировать это так, как будто следующая вещь в программе будет структурой (или возвращает структуру).
Что-то вроде этого:
struct MyStructType { int x; int y; } int foo() {}
может привести к огромному количеству ошибок, возможно, включая сообщения:
extraneous ‘int’ ignored
Все это из-за одного символа! Лучше всего начать с самого верха.
Анализ сообщения об ошибке
Большинство сообщений от компилятора будет состоять как минимум из четырех вещей:
- тип сообщения — предупреждение или ошибка;
- исходный файл, в котором появилась ошибка;
- строка ошибки;
- краткое описание того, что работает неправильно.
Вывод g++ для указанной выше программы может выглядеть следующим образом (ваши результаты могут отличаться, если вы используете другой компилятор):
foo.cc:7: error: semicolon missing after struct declaration
foo.cc это имя файла. 7 — номер строки, и ясно, что это ошибка. Короткое сообщение здесь весьма полезно, поскольку оно показывает именно то, что не правильно. Заметим, однако, что сообщение имеет смысл только в контексте программы. Оно не сообщает, в какой структуре не хватает запятой.
Более непонятным является другое сообщение об ошибке из той же попытки компиляции:
extraneous ‘int’ ignored
Программист должен выяснить, почему это произошло. Обратите внимание еще раз, что эта ошибка была вызвана проблемой в начале программы, не в строке 8, а раньше, когда в структуре не хватает точки с запятой. К счастью, понятно, что определение функции для foo было в порядке, это говорит нам о том, что ошибка должна быть где-то в другом месте программы. На самом деле, она должна быть в программе раньше — вы не будете получать сообщение об ошибке, которое указывает на синтаксическую ошибку до строки, на которой ошибка на самом деле произошла.
Это руководящий принцип вычисления ошибок компилятора: если сомневаетесь, посмотрите в программе раньше. Так как синтаксические ошибки могут позже иметь серьезные последствия, вполне возможно, что компилятор указывал номер строки, в которой на самом деле не было синтаксической ошибки!
Будет гораздо хуже, если компилятор не будет сообщать вам, что произошло ранее в программе. Даже первая ошибка компилятора, которую вы получите, может быть связана с несколькими строками до указанного предупреждения.
Обработка непонятных или странных сообщений
Есть несколько особенно сложных типов ошибок компилятора. Первый — это необъявленная переменная, которую, как вам кажется, вы объявили. Часто, вы можете указать, где именно переменная была объявлена! Проблема в том, что часто переменная просто написана с ошибкой. К сожалению, это довольно трудно увидеть, так как обычно мы читаем то, что ожидаем, а не то, что есть на самом деле. Кроме того, есть и другие причины, почему это может быть проблемой — например, проблемы с видимостью!
Чтобы разобраться в возможных проблемах, я делаю так: в строке, где находится якобы необъявленная переменная, надо выполнить поиск текстовым редактором слова под курсором (в качестве альтернативы можно скопировать имя переменной и выполнить поиск), и если я записал его неправильно, оно не найдется. Также не надо вводить имя переменной вручную, так как вы случайно можете ввести его правильно.
Второе непонятное сообщение:
unexpected end of file
Что происходит? Почему конец файла будет «неожиданным» ? Ну, здесь главное думать как компилятор; если конец файла является неожиданным, то он, должно быть, чего-то ждет. Что бы это могло быть? Ответ, как правило, «завершение». Например, закрывающие фигурные скобки или закрывающие кавычки. Хороший текстовый редактор, который выполняет подсветку синтаксиса и автоматический отступ, должен помочь исправить некоторые из этих ошибок, что позволяет легче обнаружить проблемы при написании кода.
В конечном счете, если сообщение непонятное, то подходите к проблеме, думая, как компилятор пытается интерпретировать файл. Это может быть трудно, когда вы только начинаете, но если вы обращаете внимание на сообщения и попробуете понять, что они могли бы означать, вы быстро привыкнете к общим закономерностям.
Наконец, если ничего не работает, вы всегда можете просто переписать несколько строк кода, чтобы убрать любые скрытые синтаксические ошибки, которые вы могли не увидеть. Это может быть опасно, так как вы можете переписать не ту секцию, но это может помочь.
Ошибки компоновщика
После того как вы окончательно исправили все ошибки синтаксиса, вздремнули, перекусили пару раз и морально подготовили себя к правильной компиляции программы, вы все равно можете столкнуться с ошибками компоновщика. Их часто довольно сложно исправить, потому что они не обязательно являются результатом того, что написано в вашей программе. Я вкратце опишу типичные видов ошибок компоновщика, которые можно ожидать, и некоторые пути их решения.
У вас могут возникнуть проблемы с тем, как вы настроили свой компилятор. Например, даже если включить нужные заголовочные файлы для всех ваших функций, вы все равно должны предоставить вашему компоновщику правильный путь в библиотеку, которая имеет фактическую реализацию. В противном случае, вы получите сообщение об ошибке:
undefined function
Обратите внимание на поддержку этих функций компилятором (это может произойти, если вы включите собственное объявление функции, чтобы обойти ошибку во время компиляции). Если ваш компилятор поддерживает эту функцию, то для решения проблемы обычно требуются конкретные настройки компилятора. Вам следует сообщить компилятору, где искать библиотеки и убедиться, что библиотеки были установлены правильно.
Ошибки компоновщика могут произойти в функциях, которые вы объявили и определили, если вы не включили все необходимые объектные файлы в процесс связывания. Например, если вы пишете определение класса в
myClass.cpp
, а ваша основная функция в myMain.cpp
, компилятор создаст два объектных файла, myClass.o и myMain.o, а компоновщику будут нужны оба из них для завершения создания новой программы. Если оставить myClass.o
, то у него не будет определения класса, даже если вы правильно включите myClass.h
!
Иногда появляются незначительные ошибки, когда компоновщик сообщает о более чем одном определении для класса, функции или переменной. Эта проблема может появиться по нескольким причинам: во-первых, у объекта может быть два определения — например, две глобальные переменные объявлены как внешние переменные, чтобы быть доступными за пределами файла исходного кода. Это относится как к функциям, так и к переменным, и это, на самом деле, нередко случается. С другой стороны, иногда это проблема с директивами компоновщика; несколько раз я видел, как люди включают несколько копий одного и того же объектного файла в процесс связывания. И бинго, у вас есть несколько определений. Типичным проявлением этой проблемы является то, что у целого ряда функций есть несколько определений.
Последний странный тип ошибки компоновщика — сообщение
undefined reference to main
Данная ошибка компоновщика отличается от других тем, что она может не иметь ничего общего с объектом, включая файлы или правильные пути к вашей библиотеке. Напротив, это означает, что компоновщик пытался создать исполняемый файл и не смог понять, где расположена функция main()
. Это может случиться, если вы забыли включить основную функцию, или, если вы попытаетесь скомпилировать код, который никогда не был отдельным исполняемым файлом (например, если вы попытались скомпилировать библиотеку).
From Wikipedia, the free encyclopedia
Compilation error or compile error refers to a state when a compiler fails to compile a piece of computer program source code, either due to errors in the code, or, more unusually, due to errors in the compiler itself. A compilation error message often helps programmers debugging the source code. Although the definitions of compilation and interpretation can be vague, generally compilation errors only refer to static compilation and not dynamic compilation. However, dynamic compilation can still technically have compilation errors,[citation needed] although many programmers and sources may identify them as run-time errors. Most just-in-time compilers, such as the Javascript V8 engine, ambiguously refer to compilation errors as syntax errors since they check for them at run time.[1][2]
Examples[edit]
Common C++ compilation errors[edit]
- Undeclared identifier, e.g.:
doy.cpp: In function `int main()':
[3]
doy.cpp:25: `DayOfYear' undeclared (first use this function)
This means that the variable «DayOfYear» is trying to be used before being declared.
- Common function undeclared, e.g.:
xyz.cpp: In function `int main()': xyz.cpp:6: `cout' undeclared (first use this function)
[3]
This means that the programmer most likely forgot to include iostream.
- Parse error, e.g.:
somefile.cpp:24: parse error before `something'
[4]
This could mean that a semi-colon is missing at the end of the previous statement.
Internal Compiler Errors[edit]
An internal compiler error (commonly abbreviated as ICE) is an error that occurs not due to erroneous source code, but rather due to a bug in the compiler itself. They can sometimes be worked around by making small, insignificant changes to the source code around the line indicated by the error (if such a line is indicated at all),[5][better source needed] but sometimes larger changes must be made, such as refactoring the code, to avoid certain constructs. Using a different compiler or different version of the compiler may solve the issue and be an acceptable solution in some cases. When an internal compiler error is reached many compilers do not output a standard error, but instead output a shortened version, with additional files attached, which are only provided for internal compiler errors. This is in order to insure that the program doesn’t crash when logging the error, which would make solving the error nigh impossible. The additional files attached for internal compiler errors usually have special formats that they save as, such as .dump
for Java. These formats are generally more difficult to analyze than regular files, but can still have very helpful information for solving the bug causing the crash.[6]
Example of an internal compiler error:
somefile.c:1001: internal compiler error: Segmentation fault Please submit a full bug report, with preprocessed source if appropriate. See <http://bugs.gentoo.org/> for instructions.
References[edit]
- ^ «Errors | Node.js v7.9.0 Documentation». nodejs.org. Retrieved 2017-04-14.
- ^ «SyntaxError». Mozilla Developer Network. Retrieved 2017-04-14.
- ^ a b «Common C++ Compiler and Linker Errors». Archived from the original on 2008-02-16. Retrieved 2008-02-12.
- ^ «Compiler, Linker and Run-Time Errors».
- ^ Cunningham, Ward (2010-03-18). «Compiler Bug». WikiWikiWeb. Retrieved 2017-04-14.
- ^ జగదేశ్. «Analyzing a JVM Crash». Retrieved 2017-04-15.
Единственная ошибка в вашем коде состоит в том, что вы забыли точку с запятой в конце второй строки, но я предполагаю, что это была типографская ошибка при составлении вашего вопроса, а не фактическая направленность вашего вопроса.
Я не вижу причин, по которым код, который вы показали, должен вызывать ошибку компиляции. Это компилируется просто отлично для меня, а значение a
это, по сути, 3.
Убедитесь сами: следующий код возвращает 3:
int main()
{
int a=1, b= 2, c=3;
a = (b,c);
return a;
}
Хитрость заключается в том, что вы используете оператор запятой, который оценивает свой первый операнд, затем отбрасывает результат, а затем оценивает второй операнд и возвращает его значение.
Однако, как отмечает Чарльз Бейли, вы должны обернуть код, показанный в вопросе, внутри функции, иначе вы получите ошибки компиляции в любом компиляторе. C++ не разрешает операторы присваивания вне функций.
100
Ошибка чтения файла
101
Ошибка открытия *.EX4 файла для записи
103
Недостаточно свободной памяти для завершения компиляции
104
Нераспознанная компилятором пустая синтаксическая единица
105
Некорректное имя файла в #include
106
Ошибка доступа к файлу в #include (возможно файл не существует)
108
Неподходящее имя для #define
109
Неизвестная команда препроцессора (допустимы #include,#define,#property,#import)
110
Неизвестный для компилятора символ
111
Функция не реализована (описание есть, тела нет)
112
Пропущена двойная кавычка («)
113
Пропущена открывающая угловая скобка (<) или двойная кавычка («)
114
Пропущена одинарная кавычка (‘)
115
Пропущена закрывающая угловая скобка «>»
116
Не указан тип в объявлении
117
Нет оператора возврата return или имеется не во всех ветках выполнения
118
Ожидалась открывающая скобка параметров вызова
119
Ошибка записи EX4
120
Некорректный доступ к элементу массива
121
Функция не имеет тип void и оператор return должен вернуть значение
122
Некорректное объявление деструктора
123
Отсутствует двоеточие «:»
124
Переменная уже объявлена
125
Переменная с таким идентификатором уже объявлена
126
Имя переменной слишком длинное (>250 символов)
127
Структура с таким идентификатором уже определена
128
Структура не определена
129
Член структуры с таким именем уже определен
130
Нет такого члена структуры
131
Нарушена парность квадратных скобок
132
Ожидается открывающая круглая скобка «(«
133
Несбалансированные фигурные скобки ( отсутствует «}» )
134
Сложно для компиляции (слишком большое ветвление, внутренний стек уровней переполнен)
135
Ошибка открытия файла на чтение
136
Недостаточно памяти для загрузки исходного файла в память
137
Ожидается переменная
138
Ссылка не может быть инициализирована
140
Ожидалось присваивание (возникает при объявлении)
141
Ожидается открывающая фигурная скобка «{«
142
Параметр может быть только динамическим массивом
143
Использование типа «void» недопустимо
144
Нет пары для «)» или «]», т.е. отсутствует «(» или «[«
145
Нет пары для «(» или «[«, т.е. отсутствует «)» или «]»
146
Некорректная размерность массива
147
Слишком много параметров (>64)
149
Этот токен тут не ожидается
150
Недопустимое использование операции (неправильные операнды)
151
Выражение типа void недопустимо
152
Ожидается оператор
153
Неправильное использование break
154
Ожидается точка с запятой «;»
155
Ожидается запятая «,»
156
Тип должен быть определен как класс, а не как структура
157
Ожидалось выражение
158
В HEX встречается «не HEX символ» или слишком длинное число (количество цифр > 511)
159
Строка-константа имеет более 65534 символов
160
Определение функции здесь недопустимо
161
Неожиданный конец программы
162
Форвардная декларация для структур запрещена
163
Функция с таким именем уже определена и имеет иной тип возвращаемого значения
164
Функция с таким именем уже определена и имеет иной набор параметров
165
Функция с таким именем уже определена и реализована
166
Перегрузка функции для данного вызова не найдена
167
Функция с возвращаемым значением типа void не может возвращать значение
168
Функция не определена
170
Ожидается значение
171
В выражении case допустимы только целочисленные константы
172
Значение для case в этом switch уже использовано
173
Ожидается целочисленное значение
174
В выражении #import ожидается имя файла
175
Выражения на глобальном уровне не допустимы
176
Пропущена круглая скобка «)» перед «;»
177
Слева от знака равенства предполагается переменная
178
Результат выражения не используется
179
Объявление переменных в case недопустимо
180
Неявное преобразование из строки в число
181
Неявное преобразование числа в строку
182
Неоднозначный вызов перегруженной функции (подходят несколько перегрузок)
183
Недопустимый else без соответствующего if
184
Недопустимый case или default без соответствующего switch
185
Недопустимое использование эллипсиса
186
Инициализирующая последовательность имеет большее количество элементов чем инициализируемая переменная
187
Ожидается константа для case
188
Требуется константное выражение
189
Константная переменная не может быть изменена
190
Ожидается закрывающая скобка или запятая (объявление члена массива)
191
Идентификатор перечисления уже используется
192
Перечисление не может иметь модификаторов доступа (const, extern, static)
193
Член перечисления уже объявлен с другим значением
194
Существует переменная, определенная с таким же именем
195
Существует структура, определенная с таким же именем
196
Ожидается имя члена перечисления
197
Ожидается целочисленное выражение
198
Деление на ноль в константном выражении
199
Неверное количество параметров в функции
200
Параметром по ссылке должна быть переменная
201
Ожидается переменная такого же типа для передачи по ссылке
202
Константная переменная не может быть передана по неконстантной ссылке
203
Требуется целочисленная положительная константа
204
Ошибка доступа к защищенному члену класса
205
Импорт уже определен по другому пути
208
Исполняемый файл не создан
209
Для индикатора не найдена точка входа ‘OnCalculate’
210
Оператор continue может быть использован только внутри цикла
211
Ошибка доступа к private(закрытому) члену класса
213
Метод структуры или класса не объявлен
214
Ошибка доступа к private(закрытому) методу класса
216
Копирование структур с объектами недопустимо
218
Выход индекса за границы массива
219
Недопустима инициализация массивов в объявлении структуры или класса
220
Конструктор класса не может иметь параметров
221
Деструктор класса не может иметь параметров
222
Метод класса или структуры с таким именем и параметрами уже объявлен
223
Ожидается операнд
224
Метод класса или структуры с таким именем есть, но с другими параметрами (объявление!=реализация)
225
Импортируемая функция не описана
226
Функция ZeroMemory() не применима для классов с защищенными членами или наследованием
227
Неоднозначный вызов перегруженной функции (точное совпадение параметров для нескольких перегрузок)
228
Ожидается имя переменной
229
Ссылку нельзя объявить в этом месте
230
Уже используется в качестве имени перечисления
232
Ожидается класс или структура
235
Нельзя вызывать delete для удаления массива
236
Ожидается оператор ‘ while ‘
237
В delete должен быть указатель
238
default для этого switch уже есть
239
Синтаксическая ошибка
240
Escape-последовательность может встретиться только в строках ( начинается с ‘\’ )
241
Требуется массив – квадратная скобка ‘[‘ не относится к массиву либо в качестве параметра-массива подают не массив
242
Не может быть инициализировано посредством инициализирующей последовательности
243
Импорт не определен
244
Ошибка оптимизатора на синтаксическом дереве
245
Объявлено слишком много структур (упростите программу)
246
Преобразование параметра недопустимо
247
Некорректное использование оператора delete
248
Нельзя объявить указатель на ссылку
249
Нельзя объявить ссылку на ссылку
250
Нельзя объявить указатель на указатель
251
Недопустимо объявление структуры в списке параметров
252
Недопустимая операция приведения типов
253
Указатель можно объявить только для класса или структуры
256
Необъявленный идентификатор
257
Ошибка оптимизатора исполняемого кода
258
Ошибка генерации исполняемого кода
260
Недопустимое выражение для оператора switch
261
Переполнение пула строковых констант, упростите программу
262
Невозможно преобразовать к перечислению
263
Нельзя использовать virtual для данных (членов класса или структуры)
264
Нельзя вызвать защищенный метод класса
265
Переопределяемая виртуальная функция возвращает другой тип
266
Класс нельзя наследовать от структуры
267
Структуру нельзя наследовать от класса
268
Конструктор не может быть виртуальным (спецификатор virtual недопустим)
269
Структура не может иметь виртуальных методов
270
Функция должна иметь тело
271
Перегрузка системных функций (функций терминала) запрещена
272
Спецификатор const недопустим для функций, не являющихся членом класса или структуры
274
Нельзя менять члены класса в константном методе
276
Неподходящая инициализирующая последовательность
277
Пропущено значение по умолчанию для параметра (специфика объявления параметров по умолчанию)
278
Переопределение параметра по умолчанию (в объявлении и реализации разные значения)
279
Нельзя вызвать неконстантный метод для константного объекта
280
Для доступа к членам требуется объект (поставлена точка для не класса/структуры)
281
Имя уже объявленной структуры нельзя использовать при объявлении
284
Неразрешенное преобразование (при закрытом наследовании)
285
Структуры и массивы не могут быть использованы в качестве input-переменных
286
Спецификатор const недопустим для конструктора/деструктора
287
Неправильное строковое выражение для типа datetime
288
Неизвестное свойство (#property)
289
Некорректное значение для свойства
290
Некорректный индекс для свойства в #property
291
Пропущен параметр вызова – < func(x,) >
293
Объект должен быть передан по ссылке
294
Массив должен быть передан по ссылке
295
Функция была декларирована как экспортируемая
296
Функция не была декларирована как экспортируемая
297
Экспортировать импортируемую функцию нельзя
298
Импортируемая функция не может иметь такого параметра (нельзя передавать указатель, класс или структуру, содержащую динамический массив, указатель, класс и т.д.)
299
Должен быть класс
300
Секция #import не закрыта
302
Несоответствие типов
303
extern-переменная уже инициализирована
304
Не найдено ни одной экспортируемой функции или стандартной точки входа
305
Явный вызов конструктора запрещен
306
Метод был объявлен константным
307
Метод не был объявлен константным
308
Некорректный размер ресурсного файла
309
Некорректное имя ресурса
310
Ошибка открытия файла ресурса
311
Ошибка чтения файла ресурса
312
Неизвестный тип ресурса
313
Некорректный путь к файлу ресурса
314
Указанное имя ресурса уже используется
315
Ожидались параметры макроса
316
После имени макроса должен быть пробел
317
Ошибка в описании параметров макроса
318
Неверное число параметров при использовании макроса
319
Превышение максимального количества(16) параметров для макроса
320
Макрос слишком сложный, требуется упрощение
321
Параметром EnumToString() может быть только перечисление
322
Имя ресурса слишком длинное
323
Неподдерживаемый формат изображения (допустим только BMP-формат с глубиной цвета 24 или 32 бита)
324
Объявление массива внутри оператора запрещено
325
Функцию можно определить только на глобальном уровне
326
Данное объявление недопустимо для текущей области видимости (области определения)
327
Инициализация статичных переменных значениями локальных недопустима
328
Недопустимое объявление массива объектов, не имеющих конструктора по умолчанию
329
Список инициализации разрешен только для конструкторов
330
Отсутствует определение функции после списка инициализации
331
Список инициализации пуст
332
Инициализация массива в конструкторе запрещена
333
В списке инициализации запрещено инициализировать члены родительского класса
334
Ожидалось выражение целого типа
335
Требуемый объем памяти для массива превышает максимально допустимое значение
336
Требуемый объем памяти для структуры превышает максимально допустимое значение
337
Требуемый объем памяти для переменных, объявленных на глобальном уровне, превышает максимально допустимое значение
338
Требуемый объем памяти для локальных переменных превышает максимально допустимое значение
339
Конструктор не определен
340
Недопустимое имя для файла иконки
341
Не удалось открыть файла иконки по указанному пути
342
Файл иконки некорректен и не соответствует формату ICO
343
Повторная инициализация члена в конструкторе класса/структуры с помощью списка инициализации
344
Инициализация статических членов в списке инициализации конструктора не допускается
345
Инициализация нестатического члена класса/структуры на глобальном уровне запрещена
346
Имя метода класса/структуры совпадает с ранее объявленным именем члена
347
Имя члена класса/структуры совпадает с ранее объявленным именем метода
348
Виртуальная функция не может быть объявлена как static
349
Модификатор const недопустим для статической функции
350
Конструктор или деструктор не могут быть статическими
351
Нельзя обращаться к нестатическому члену/методу класса или структуры из статической функции
352
После ключевого слова operator ожидается перегружаемая операция (+,-,[],++,— и т.д.)
353
Не все операции можно перегружать в MQL4
354
Определение не соответствует объявлению
355
Указано неверное количество параметров для оператора
356
Не обнаружено ни одной функции-обработчика события
357
Методы не могут быть экспортируемыми
358
Нельзя приводить указатель на константный объект к указателю на неконстантный объект
359
Шаблоны классов пока не поддерживаются
360
Перегрузка шаблонов функций пока не поддерживается
361
Невозможно применить шаблон функции
362
Неоднозначный параметр в шаблоне функции (подходят несколько типов параметра)
363
Невозможно определить к какому типу параметра приводить аргумент шаблона функции
364
Неверное количество параметров в шаблоне функции
365
Шаблон функции не может быть виртуальным
366
Шаблоны функций не могут быть экспортированы
367
Нельзя импортировать шаблоны функций
368
Cтруктуры, содержащие объекты, недопустимы
369
Массивы строк и структуры, содержащие объекты, недопустимы
370
Статический член класса/структуры должен быть явно инициализирован
371
Ограничение компилятора: строка не может содержать более 65 535 символов
372
Несогласованные #ifdef/#endif
373
Результатом выполнения функции не может быть объект класса, так как отсутствует конструктор копирования
374
Нельзя использовать нестатические члены и/или методы при инициализации статической переменной
375
OnTesterInit() нельзя использовать без объявления обработчика OnTesterDeinit()
376
Имя локальной переменной совпадает с именем одного из параметров функции
377
Нельзя использовать макросы __FUNCSIG__ и __FUNCTION__ вне тела функции
378
Недопустимый возвращаемый тип. Например, такая ошибка будет выдана для функций, импортированных из DLL, которые возвращают структуру или указатель в качестве результата
379
Ошибка при использовании шаблона
380
Не используется
381
Недопустимый синтаксис при объявлении чисто виртуальной функции, разрешено «=NULL» или «=0»
382
Только виртуальные функции могут быть объявлены со спецификатором чисто виртуальной функции («=NULL» или «=0»)
383
Нельзя создать экземпляр абстрактного класса
384
Для динамического приведения с помощью оператора dynamic_cast типом назначения должен быть указатель на пользовательский тип
385
Ожидается тип «указатель на функцию»
386
Указатели на методы не поддерживаются
387
Ошибка – невозможно определить тип указателя на функцию
388
Приведение типа недоступно из-за закрытого наследования
389
Переменная с модификатором const должна быть проинициализирована при объявлении
Обработка ошибок и проектирование компилятора
Перевод статьи Error Handling in Compiler Designopen in new window.
Задача по обработке ошибок (Error Handling) включает в себя: обнаружение ошибок, сообщения об ошибках пользователю, создание стратегии восстановления и реализации обработки ошибок. Кроме того система обработки ошибок должна работать быстро.
Типы источников ошибок
Источники ошибок делятся на два типа: ошибки времени выполнения (run-time error) и ошибки времени компиляции (compile-time error).
Ошибки времени выполнения возникают когда программа запущена. Обычно они связаны с неверными входными данными. Примеры таких ошибок: недостаток памяти, конфликт с другим приложением, логические ошибки. Логическая ошибка означает что запуск программы не приводит к ожидаемому результату. Логические ошибки лучше всего обрабатывать тщательным тестированием и отладкой программы.
Ошибки времени компиляции возникают во время компиляции, до запуска программы. Примеры таких ошибок: синтаксическая ошибка или отсутствие файла с кодом на который есть ссылка.
Типы ошибок времени компиляции
Ошибки компиляции разделяются на:
- Лексические (Lexical): включают в себя опечатки идентификаторов, ключевых слов и операторов
- Синтаксические (Syntactical): пропущенная точка с запятой или незакрытая скобка
- Семантические (Semantical): несовместимое значение при присвоении или несовпадение типов между оператором и операндом
- Логические (Logical): недостижимый код, бесконечный цикл
Парсер, обрабатывая текст, пытается как можно раньше обнаружить ошибку. В современных средах разработки синтаксические ошибки отображаются прямо в редакторе кода, предотвращая последующий неверный ввод. Обнажение ошибки происходит когда введённый префикс не совпадает с префиксами строк верными в выбранном языке программирования. Например префикс for(;)
может привести к сообщению об ошибке, так как обычно внутри for
должно быть две точки с запятой.
Восстановление после ошибок
Базовое требование к компилятору — прервать компиляцию и выдать сообщение при появлении ошибки. Кроме этого есть несколько методов восстановления после ошибки.
Panic mode recovery
Это самый простой способ восстановления после ошибок и он предотвращает бесконечные циклы в компиляторе при попытках исправить ошибку. Парсер отклоняет следующие за ошибкой символы до того как будет обнаружен специальный символ (например, разделитель команд, точка с запятой). Такой подход адекватен если низкая вероятность нескольких ошибок в одной конструкции.
Пример: рассмотрим выражение с ошибкой (1 + + 2) + 3
. При обнаружении второго +
пропускаются все символы до следующего числа.
Phase level recovery
Производится локальное изменение входного потока чтобы исправить ошибку.
Error productions
Разработчики компиляторов знают часто встречаемые ошибки. При появлении таких ошибок могут применяться расширения грамматики для их обработки. Например: написание 5x
вместо 5*x
.
Global correction
Производится как можно меньше изменений чтобы преобразовать код с ошибкой в корректный код. Эту стратегию дорого реализовывать.