Прежде чем начать искать ошибки, стоит
определить, где именно они водятся. Перед поиском ошибок скопируйте
свой проект и работайте с копией. В крайнем случае, когда вы запутаетесь
окончательно, вы сможете вернуться к тому, с чего начинали. Только не забудьте
между исправлением ошибки и удалением рабочей копии проекта внести изменения
в основной проект!
Не забывайте и о комментариях,
которые позволяют если не найти ошибки, то хотя бы отследить, что и когда
вы делали.
Учитесь у великих!
Правило "Разделяй и властвуй" еще никто не отменял. А потому разделяйте
свою задачу на части и властвуйте. Найти ошибку или убедиться в ее отсутствии
в части программы проще, чем во всей программе в целом, особенно когда
появляется эффект интерференции ошибок, при котором ошибка начинает взаимодействовать
с другой так, что отследить их становится очень сложно.
И, тем не менее, при
отладке программисты нередко оказываются в почти безвыходной ситуации.
Некоторые ошибки я и опишу в этом разделе и подскажу, как успешно их поймать.
Error
Setting Debug Exception Hook
Если вы увидели сообщение,
показанное рис. 2.26, значит, отладчик оказался в трудном и, главное, нестабильном
положении, что обычно происходит после аварийной остановки отлаживаемого
приложения. Что делать? Попробуйте воспользоваться командой Run/Program
Reset и запустить приложение еще раз. Не помогло? Выполните команду Program/Build
All. И это не дает результата? Тогда вам придется выйти из среды разработки
и запустить ее еще раз. Самый последний совет
— проделать то же и с операционной системой...
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. Это, конечно, позволяет судить о том, что произошло,
но не дает никакой информации о том, где это произошло, так что единственный
способ найти ошибку — разделять и властвовать, т.е. пересмотреть приложение
до возникновения исключительной ситуации.
Использование
отладчика TD32.EXE
Может случиться, что,
несмотря на все возможности отладчика Delphi 4, вы столкнетесь с совершенно
неотслежимаемой ошибкой. Если это произойдет, примите мои искренние соболезнования.
Можете попытаться использовать отдельный отладчик фирмы Borland (TD32.EXE),
поставляемый в комплекте Turbo Assembler или Borland C++. В дополнении
ко всему, что есть в отладчике Delphi, TD32 имеет и то, чего в Delphi нет.
В частности, TD32 позволяет установить аппаратные точки останова, что означает,
например, останов при обращении к портам ввода-вывода или к памяти. Это
тяжелая работа, и я могу только посочувствовать вам, если вы за нее беретесь.
И учтите, что такая работа требует знания как системного программного,
так и аппаратного обеспечения.