- Главная
- Directory
- Directives
- #error – сообщение об ошибке
Директива #error выдает указанное пользователем сообщение об ошибке во время компиляции, а затем завершает компиляцию.
#error token-string
Сообщение об ошибке, эта директива выдает token-string параметр. Token-string параметр не подлежит расширения макроса. Эта директива наиболее полезна во время предварительной обработки для уведомления разработчика несогласованности программы или нарушения ограничений. Следующий пример демонстрирует ошибки при обработке во время предварительной обработки.
#if !defined(__cplusplus)
#error C++ compiler required.
#endif
Табаков Юрий
Программист
Автор и редактор проекта CuBook.PRO. Главная задача, которую я ставлю перед собой – донести до начинающих программистов удобочитаемый материал. Буду рад выслушать замечания и предложения. Не забываем ставить оценки и делать репосты =)
0 / 0 / 0 Регистрация: 28.04.2012 Сообщений: 8 |
|
1 |
|
Сообщение об любой ошибке27.09.2013, 12:01. Показов 2705. Ответов 5
Здравствуйте, Уважаемые форумчане. Я плохо знаком с борландом, начал с ним работать пару месяцев назад. Пишу большую, но однотипную программу, в ней частенько приходится вводить числа, некотрые из них с плавающей запятой, и естественно когда вводишь, буквы вместо цифр или ещё что-то, программа вылетает. Я стараюсь везде писать циклы проверки, но могу что-то всё же упустить из виду.
0 |
8385 / 6147 / 615 Регистрация: 10.12.2010 Сообщений: 28,683 Записей в блоге: 30 |
|
27.09.2013, 12:04 |
2 |
Можно… Читайте об обработке исключений в С++
1 |
1090 / 588 / 121 Регистрация: 11.11.2008 Сообщений: 1,544 |
|
27.09.2013, 12:11 |
3 |
за одно стоит почитать чем исключения отличаются от ошибок…
частенько приходится вводить числа, некотрые из них с плавающей запятой, и естественно когда вводишь, буквы вместо цифр или ещё что-то, программа вылетает. это не естественно, это происходит только тогда когда программист ничего не предпринимает Не по теме: также неплохо освежить в памяти, когда пишется предлог «о», а когда «об».
1 |
0 / 0 / 0 Регистрация: 28.04.2012 Сообщений: 8 |
|
27.09.2013, 12:21 [ТС] |
4 |
также неплохо освежить в памяти, когда пишется предлог «о», а когда «об» В яблочко. А так, спасибо, сейчас начну изучать.
0 |
Rapsod Волшебник 65 / 64 / 7 Регистрация: 21.11.2009 Сообщений: 319 |
||||||||
27.09.2013, 12:47 |
5 |
|||||||
Здравствуйте, Уважаемые форумчане. Я плохо знаком с борландом, начал с ним работать пару месяцев назад. Пишу большую, но однотипную программу, в ней частенько приходится вводить числа, некотрые из них с плавающей запятой, и естественно когда вводишь, буквы вместо цифр или ещё что-то, программа вылетает. Я стараюсь везде писать циклы проверки, но могу что-то всё же упустить из виду. Используйте try catch
Добавлено через 6 минут
P.S. Но это не по правилам. Потому что приложение нужно писать так, чтобы исключений не возникало.
1 |
0 / 0 / 0 Регистрация: 28.04.2012 Сообщений: 8 |
|
27.09.2013, 15:12 [ТС] |
6 |
Спасибо, почитал, попробовал разные варианты. Для себя понял что лучше не допускать, неопределённых условий.
0 |
IT_Exp Эксперт 87844 / 49110 / 22898 Регистрация: 17.06.2006 Сообщений: 92,604 |
27.09.2013, 15:12 |
6 |
Прежде чем начать искать ошибки, стоит определить, где именно они водятся. Перед поиском ошибок скопируйте свой проект и работайте с копией. В крайнем случае, когда вы запутаетесь окончательно, вы сможете вернуться к тому, с чего начинали. Только не забудьте между исправлением ошибки и удалением рабочей копии проекта внести изменения в основной проект!
Не забывайте и о комментариях, которые позволяют если не найти ошибки, то хотя бы отследить, что и когда вы делали.
Учитесь у великих! Правило «Разделяй и властвуй» еще никто не отменял. А потому разделяйте свою задачу на части и властвуйте. Найти ошибку или убедиться в ее отсутствии в части программы проще, чем во всей программе в целом, особенно когда появляется эффект интерференции ошибок, при котором ошибка начинает взаимодействовать с другой так, что отследить их становится очень сложно.
И, тем не менее, при отладке программисты нередко оказываются в почти безвыходной ситуации. Некоторые ошибки я и опишу в этом разделе и подскажу, как успешно их поймать.
Error Setting Debug Exception Hook
Если вы увидели сообщение, показанное рис. 2.26, значит, отладчик оказался в трудном и, главное, нестабильном положении, что обычно происходит после аварийной остановки отлаживаемого приложения. Что делать? Попробуйте воспользоваться командой Run/Program Reset и запустить приложение еще раз. Не помогло? Выполните команду Program/Build All. И это не дает результата? Тогда вам придется выйти из среды разработки и запустить ее еще раз. Самый последний совет — проделать то же и с операционной системой…
Рис. 2.26. Сообщение Error setting debug exception hook
Access Violation
Нарушение доступа — это ночной кошмар программистов, ужас, летящий на крыльях ночи… Весь ужас в том, что очень часто это — мина с часовым механизмом, внезапно взрывающаяся после сотен, а то и тысяч строк пройденного кода.
В действительности access violation — всего лишь простая ошибка, означающая, что ваше приложение «получило по рукам» от операционной системы за попытку влезть в область памяти, ему не принадлежащей. Когда вы получаете сообщение об этом (рис. 2.28), вам рассказывают, кто (первое число) и куда (второе число) пытался залезть. Первое число предоставляет адрес инструкции, попытавшейся нарушить границы, а второе указывает, куда именно хотела обратиться инструкция-нарушительница.
Вернитесь в среду, выберите команду Search/Find Error, введите адрес ошибки (первое число в сообщении) в поле ввода диалогового окна, щелкните на кнопке ОК и читайте подходящую молитву. Если вам повезет, в окне появится строка, вызвавшая ошибку. Гораздо чаще этого не происходит, так как ошибка оказывается где-то в VCL или библиотеке, скомпилированной без отладочной информации, и вызывает ее передача неверного параметра в функцию, при отработке которого и происходит ошибка доступа.
Даже скомпилировав VCL с отладочной информацией, вы, скорее всего, сможете получить только имя функции, вызвавшей ошибку, и вам все равно придется потратить немало времени на поиски ошибки где-то совсем в другом месте.
Stack Overflow
Переполнение стека (stack overflow) — ошибка, появляющаяся в 32-битовом приложении гораздо реже, чем в 16 битовом, так как размер стека в этом случае существенно больше. Практически есть только один путь получить эту ошибку в Delphi 4 — попасть в бесконечную рекурсию. Например, приведенная ниже функция неминуемо должна вызвать переполнение стека.
function BlowTheStack(I: Integer); Integer;
var J: Integer;
begin
J:= 2;
Result:= BlowTheStack(I*J);
end;
Каждый раз при рекурсивном вызове в стеке резервируется место для локальной переменной J и адреса возврата. Поскольку условия возврата из рекурсии нет, переполнение стека неминуемо.
Конечно же, бесконечная рекурсия — не единственная причина возникновения ошибки такого рода, но это первое, что стоит отследить при переполнении стека.
External Exceptions
Сообщение об ошибке External exception, показанное на рис. 2.27, может вызываться порожденной приложением исключительной ситуацией, перехваченной He-Delphi-модулем (DLL). Коды ошибок определены в файле WINDOWS.PAS, включенном в поставку Delphi; их символические имена имеют вид STATUS_xxxxx. Например, показанная на рис. 2.28, исключительная ситуация C000001D— исключительная ситуация STATUS_ILLEGAL_INSTRUCTION. Это, конечно, позволяет судить о том, что произошло, но не дает никакой информации о том, где это произошло, так что единственный способ найти ошибку — разделять и властвовать, т.е. пересмотреть приложение до возникновения исключительной ситуации.
Рис. 2.27. Сообщение о нарушении доступа
Рис. 2.28. Сообщение о внешней исключительной ситуации
Использование отладчика TD32.EXE
Может случиться, что, несмотря на все возможности отладчика Delphi 4, вы столкнетесь с совершенно неотслежимаемой ошибкой. Если это произойдет, примите мои искренние соболезнования. Можете попытаться использовать отдельный отладчик фирмы Borland (TD32.EXE), поставляемый в комплекте Turbo Assembler или Borland C++. В дополнении ко всему, что есть в отладчике Delphi, TD32 имеет и то, чего в Delphi нет. В частности, TD32 позволяет установить аппаратные точки останова, что означает, например, останов при обращении к портам ввода-вывода или к памяти. Это тяжелая работа, и я могу только посочувствовать вам, если вы за нее беретесь. И учтите, что такая работа требует знания как системного программного, так и аппаратного обеспечения.
Разные MessageBox’ы
На этом занятии мы рассмотрим два пособа вывода на экран окна сообщения — ShowMessage и MessageDlg. Первая из них позволяет вывести на экран простое окно сообщения, вторая — окно с дополнительными параметрами (несколько кнопок, иконка и др.)
Обе эти функции выводят модальное окно.
Начнем с ShowMessage.
Вот сразу пример:
...
ShowMessage("Ошибка!");
...
Этот пример выведет, естественно, сообщение «Ошибка!». Никаких дополнительных параметров у функции ShowMessage нет — только текст вообщения.
А вот функция MessageDlg позволяет задавать для выводимого окна сообщения ряд дополнительных параметров. Вот пример использования этой функции:
...
MessageDlg("Внимание!", mtInformation, TMsgDlgButtons() << mbNo << mbYes, 0);
...
Вообще-то это относится скорее к WinAPI, чем к VCL. Но в следующем шаге будут рассмотрены функции API, для которых подобная функция нужна
Эта функция используется обычно в сочетании с FormatMessage. Подробное описание последней займет довольно много места. Возьмем простой и реальный пример использования — функцию, выводящую последнее сообщение об ошибке, скажем, как AnsiString. И назовем ее… AnsiLastError.
AnsiString AnsiLastError(void) { void* cstr; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) &cstr, 0, NULL ); String res((char*)cstr); LocalFree(cstr); return res; }
Инструкция LocalFree используется здесь для освобождения памяти, занятой под буфер. Как пример использования подобной функции — ошибочный вызов API-функции FloodFill:
void __fastcall TForm1::Button1Click(TObject *Sender) { FloodFill(0,0,0,0); Application->MessageBox(AnsiLastError().c_str(),"Error",MB_OK); }
Здесь вызов функции неправилен, потому что первым параметром должен идти handle канвы, контекст устройства. Ну а NULL не особенно под это подходит. Поэтому при нажатии на кнопку выйдет окошко:
Причем на русском языке! Это, правда, у меня в региональных настройках стоит Russian, может, у кого Japanese или Africaans стоит, не знаю :). В виде, приведенном выше, эта функция дает ошибку в языке по умолчанию. Макрос MAKELANGID (вернее, это Windows поддерживает, а макрос только к LANGID преобразует) поддерживает около 44 языков (если я правильно посчитал) и еще суб-языки с разным написанием, типа кириллица-латиница.
В следующем шаге будет быстрый вариант конвертера из шага 50.