Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

Программирование на Delphi. От новичка до профессионала! 18. Отладка приложений


Информационный Канал Subscribe.Ru


 Здравствуйте, читатели, в моей жизни произошло ужасное событие с эту субботу. Мне срочно нужна психологическая помощь, кто может подсказать адресок? Сообщайте в гостевую http://mydelphi7.narod.ru

 

 18. Отладка приложений

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

18.1 Варианты компиляции и сообщения компилятора

Компиляция с последующим выполнением приложения осуществляется командой Run | Run или горячей клавишей F9. Выполнение будет проводиться только в случае, если при компиляции не обнаружены неисправимые ошибки и загрузочный модуль создан. Компиляция без последующего выполнения приложения осуществляется командой Project | Compile Project или горячими клавишами Ctrl-F9. В обоих вариантах команд компилируются только те модули, которые были изменены с момента последней компиляции. Такая выборочная компиляция позволяет в больших проектах экономить немало времени, поскольку модули, которые не изменялись, повторно не компилируются. Однако такая выборочная компиляция не всегда устраивает разработчика. Например, это не устроит вас, если вы ничего не меняли в самих модулях, а только изменили опции компилятора: например, включили ранее отключенную оптимизацию кода (флажок Optimization страницы Compiler окна Project Options, которое вы можете вызвать командой Project | Options) или убрали ранее использованную поддержку пакетов времени выполнения.

В этих случаях вам надо перекомпилировать все модули проекта, независимо от того, изменялись они или нет. Для такой принудительной компиляции существует команда Project | Build Project. Она компилирует все файлы проекта независимо от времени их предыдущей компиляции. В меню Project имеется еще две команды компиляции: Compile All Projects и Build All Projects. Если вы работаете только с одним проектом, то эти команды идентичны рассмотренным командам Compile Project и Build Project. Но если вы работаете с группой проектов, то первая из этих команд осуществляет выборочную компиляцию всех измененных с момента последней компиляции файлов всех проектов группы, а вторая принудительно компилирует все файлы всех проектов группы.

В результате компиляции могут быть сделаны замечания — Hint, предупреждения — Warning и сообщения об ошибках — Error. Чтобы посмотреть эти сообщения, давайте сделаем простое приложение с ошибочными операторами. Начните новое приложение, перенесите на форму окно редактирования Edit и кнопку. В окно занесите (в свойство Text) число 10. Объявите глобальные переменные i и j типа word, а в обработчик щелчка кнопки введите указанные ниже операторы. При этом весь раздел implementation вашего приложения должен иметь вид:

Implementation
{$R *.DFM}
var i,j:word;

procedure TForm1.Button1Click(Sender: TObject);
var A:double;
begin
for i:=1 to 5 do
A := A * A;
Edit1.Text := B;
end;


Попробуйте нажать клавишу F9. Вы увидите в окне Редактора Кода внизу сообщения о замечаниях и ошибках. Первое сообщение:

[Warning] Unit1.pas(30): For loop control variable must be simple local variable
([Предупреждение] модуль Unit1.pas, строка 30: Для цикла For управляющая переменная должна быть простой локальной переменной)

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

Следующее сообщение:

[Error] Unit1.pas(32): Undeclared identifier: 'В'
([Ошибка] модуль Unit1.pas, строка 32: Необъявленный идентификатор 'В')

Это уже сообщение об ошибке. В данном случае вместо переменной А мы указали переменную В, которая не была объявлена. Строка кода с этой ошибкой выделена в окне Редактора Кода, и курсор остановился около необъявленного идентификатора. Ошибки такого рода будут у вас чаще всего — это результат описки в имени переменной, компонента, свойства, метода, функции.

Если в приложении несколько ошибок, то соответственно будет и несколько сообщений о них. Перейдя в окно сообщений и сделав двойной щелчок на каком-нибудь из сообщений, вы увидите, что в окне Редактора Кода выделится строка, соответствующая этому сообщению.

Поскольку рассмотренная выше ошибка неисправима, то в данном примере вь видите внизу последнее сообщение:

[Fatal Error] Project1.dpr(5): Could not compile used unit 'Unit1.pas'
([Неисправимая ошибка] проект Project1.dpr, строка 5: Невозможно компилировать используемый модуль 'Unit1.pas')

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

Если вы исправите в ошибочном операторе переменную В на А, то получите новое сообщение об ошибке:
[Error] Unit1.pas(32): Incompatible types: 'String' and 'Double'
([Ошибка] модуль Unit1.pas, строка 32: Несовместимые типы 'String' и 'Double')

Действительно, нельзя присвоить переменной типа string — тексту окна редактирования Text значение переменной А, объявленной как double. Подобные ошибки использования несовместимых типов тоже очень распространены и вы, вероятно, не раз невольно будете их делать.

Правильный оператор в нашем примере должен иметь вид:
Edit1.Text := FloatToStr(A);

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

[Hint] Unit1.pas(25): Variable 'j' is declared but never used in 'Unit1’
([Замечание] модуль Unit1.pas, строка 25: Переменная 'j' объявлена, но нигде в 'Unit1 не используется)

Действительно, мы объявили переменную j, но не использовали ее. Если эта переменная — заготовка для каких-то будущих процедур, то это замечание можно проигнорировать. Но если переменная j действительно не нужна, то её объявление лучше удалить из текста, так как под эту переменную тратится, конечно, небольшой, но совершенно бессмысленный объем памяти.

С этим замечанием мы разобрались. Но у нас появилось еще одно более серьезное предупреждение:

[Warning] Uhitl.pas(31): Variable 'A' might not have been initialized ([Предупреждение] модуль Unit1.pas, строка 31: Переменная 'А' может оказаться не инициализированной).

Действительно, мы ввели локальную переменную А и нигде не задали ее начальное значение. С точки зрения компилятора это не ошибка, а замечание. Но для программы это действительно ошибка, так как, строго говоря, неизвестно, чему будет равно значение этой переменной при входе в процедуру. Если мы хотим. например, чтобы при каждом выполнении процедуры значение А равнялось 1, мы должны добавить перед циклом оператор:

A:=1;

Если же мы хотим, чтобы в переменной А накапливался результат при каждом щелчке на кнопке, мы должны убрать ее объявление из процедуры и ввести ее объявление после объявления раздела implementation, задав для неё начальное
значение 1:

var A:double=1;

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

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

Пусть в нашем примере мы хотим накапливать результат в переменной А. Объявим А как глобальную переменную. Это нам будет полезно в дальнейшем для наблюдения её изменения во время выполнения. Но для сохранения А мы выберем не те варианты, которые были указаны выше, а третий вариант, при котором начальное значение А при щелчке на кнопке берётся из окна Edit1, и в этом же окне хранится значение, полученное после предыдущего щелчка на кнопке. Тогда перед выполнением цикла надо прочитать значение А из окна Edit1.

И ёще одно замечание. Далее мы будем использовать наше приложение для вылавливания ошибок времени выполнения. Но при использовании Delphi 7 результаты этих ошибок могут быть различными в зависимости от настройки ИСР и вашего компьютера. Чтобы избежать этого, давайте сделаем в приложении ещё некоторые добавления. Введем оператор uses, ссылающийся на модуль Math, и добавим обработчик события OnCreate нашей формы вида:

SetExceptionMask([exInvalidOp, exDenormalized, exZeroDivide, exOverflow, exUnderflow, exPrecision]);

На смысле этих добавлений мы сейчас останавливаться не. После всех исправлений ваш код должен иметь вид:

Implementation
{$R *.dfrn}
uses Math;
var A:double;
procedure TForm1.Button1Click(Sender: TObject) ;
var i: word;
begin
A := StrToFloat(Edit1.Text);
for i:=1 to 5 do
A := A * A;
Edit1.Text := FloatToStr(A);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin SetExceptionMask[exInvalidOp, exDenormalized, exZeroDivide, exOverflow, exUnderflow, exPrecision]);
end;
end.


Теперь откомпилируйте ваше приложение и выполните его.
 

 

Сайт рассылки http://mydelphi7.narod.ru, на котором есть архив рассылки, также гостевая книга, переводчик.

Копировать, размещать, продавать представленную информацию запрещается.

 

Rambler's Top100



http://subscribe.ru/
E-mail: ask@subscribe.ru
Отписаться
Убрать рекламу

В избранное