Вверх ↑
Пакеты 
HiAsm4
Windows 
Статьи - Отладка

Отладка
Введение
   Как и в любой другой среде разработки, отладка применяется для того, чтобы "отлаживать" программу, т.е. искать в ней ошибки, неточности в работе или участки схемы, тормозящие выполнение приложения. Кроме того, нередко отладочным режимом пользуются для того, чтобы лучше понять работу программы и проследить циркуляцию данных в ней. Иногда нужную информацию о работе элемента гораздо быстрее и проще получить в отладочном режиме, чем поиском по справочным материалам или иным источникам информации. Далее в статье как раз и будут рассмотрены эти два основных назначения режима Отладки.
Инструменты отладки
   Прежде чем приступить к описанию режимов отладочного режима следует познакомится с тем, а какие вообще инструменты предоставляет Конструктор программ для работы с ним.
   Основные команды управления режимом отладки расположены на панели инструментов как показано на рисунке справа. Назначение кнопок слева направо:

- запуск программы в обычном режиме. В нем не доступна трассировка приложения по шагам, но присутствует возможность просмотра и мониторинга данных в потоке между элементами схемы
- зупуск приложения в отладочном режиме. Отличается от предыдущего тем, что доступна трассировка схемы с момента получения управления любой из активных точек останова (элемент Debug).
- трассировка схемы после остановки на точке Debug в отладочном режиме. Во всех иных случаях команда не доступна.
- принудительное завершение работы приложения
- компиляция программы. Отличается от первой команды только тем, что не запускает приложение после компиляции.
Трассировка схемы
   Рассмотрим простой пример трассировки схемы по шагам в режиме отладки. Для этого необходимо открыть в Конструкторе пример ниже:

Add(MainForm,2953706,21,105)
{
}
Add(Button,10171949,119,126)
{
Left=60
Top=100
link(onClick,16089781:doEvent,[])
}
Add(Edit,6890024,210,70)
{
Left=135
Top=50
}
Add(Label,1717154,280,126)
{
Left=230
Top=105
}
Add(DoData,2696935,210,126)
{
link(onEventData,1717154:doText,[])
link(Data,6890024:Text,[])
}
Add(Debug,16089781,168,126)
{
WEName="onClick"
VDName=""
link(onEvent,2696935:doData,[])
}
Схема достаточно простая: после нажатия кнопки на форме элемент DoData берет данные из поля ввода (Edit) и отправляет их на элемент Label. В потоке между кнопкой и DoData вставлена точка останова, с которой мы и будем осуществлять трассировку схемы.

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

   Второе окно - это окно отладки самого приложения, которое отображается на экране в том случае, если в схеме есть хотя бы одна активная точка останова:

   В таблице этого окна выводятся имена каналов всех точек останова, размещенных на схеме. В примере выше используется только одна точка останова с одним активным каналом (между элементами Button и DoData) - именно она и присутствует в списке на рисунке выше.

   Попробуем нажать кнопку "Push" на форме. Поскольку программа запущена в режиме отладки и сразу после события onClick идет точка останова, то приложение "зависнет", а среда в это время отобразит активный поток (на рисунке справа) и сделает доступной кнопку трассировки схемы. Это состояние программы называется "режим трассировки приложения по шагам". При этом отлаживаемая программа на самом деле не висит, а находится в постоянном ожидание команд от среды. Теперь из пяти кнопок (см. первый рисунок данной статьи) доступны только три средние:

- продолжить выполнение программы без трассировки
- переход на следующий шаг(собственно трассировка)
- остановка программы

   Попробуйте понажимать кнопку трассировки (или клавишу F8) и вы увидите, как среда на каждом шаге подсвечивает следующий активный поток схемы и выводит данные, находящиеся в нем, в окно отладки. При этом после отработки последнего потока между элементами DoData и Label программа вновь "оживет", а кнопка трассировки перестанет быть доступной. Это означает, что выполнение алгоритмической ветки схемы полностью завершено и приложение вновь ожидает действия от пользователя.

   Если вы внимательно следили за процессом трассировки схемы, то могли заметить, что при получении данных с поля ввода канал между элементами DoData и Edit подсвечивался два шага, а не один. Связано это с тем, что канал "поток-данные" выполняется в два этапа - сначала идет, образно выражаясь, запрос данных "наверх", а только потом уже их получение "вниз". В следующей схеме хорошо видно, что между запросом данных и их фактическим получением может происходить еще множество событий:

Add(MainForm,2953706,21,105)
{
}
Add(Button,10171949,119,189)
{
Left=60
Top=100
Data=Integer(1)
link(onClick,16089781:doEvent,[])
}
Add(Label,1717154,287,189)
{
Left=230
Top=105
}
Add(Debug,16089781,168,189)
{
WEName="onClick"
VDName=""
link(onEvent,9238293:doData,[])
}
Add(DoData,9238293,203,189)
{
link(onEventData,1717154:doText,[])
link(Data,16162992:GetData,[])
}
Add(EventFromData,16162992,203,133)
{
link(onEvent,12124408:doData,[])
}
Add(DoData,12124408,287,133)
{
Data=String(test)
link(onEventData,16162992:doData,[(329,139)(329,122)(191,122)(191,139)])
}
   Не исключена и такая ситуация, когда данные передаются как вниз, так и наверх (что невозможно для канала Work-Event) и поэтому двухтактное отображение получения данных элементами дает гораздо больше представления о работе схемы в целом.
Исследование элементов
   Исследование работы элемента как уже было сказано выше строится исключительно на использовании элемента Debug, расставленного в каналах между элементами. Для примера предположим, что вы не до конца понимаете как работает элемент Цикл со счетчиком(For) и хотите на практике выяснить это. Ниже дана схема, которую лучше всего использовать для этих целей:

Add(Button,4165716,161,91)
{
Left=110
Top=50
link(onClick,12918180:doFor,[])
}
Add(For,12918180,217,91)
{
End=10
link(onEvent,12986552:doText,[])
}
Add(Label,12986552,273,91)
{
Left=180
Top=50
}
   В схеме по нажатию кнопки запускается цикл, после чего он что-то и как-то выдает (а может и не выдает) на элемент Label. Вот это мы сейчас и попробуем прояснить. Для этого в схему на связь между точками onFor цикла и doCaption надписи необходимо вставить элемент Debug, в свойствах которого задать следующие значения:

- WEName - имя канала Event-Work, который мы отлаживаем. Значение свойства в принципе ни на что не влияет и необходимо только для наглядности. Определим его как onFor-doCaption
- VDName - имя канала Data-Var. Поскольку в представленной схеме не требуется отлаживать вертикальные каналы, то значение этого свойства можно сделать пустым(опять таки же это ни на что принципиально не влияет, а всего лишь уберет не нужную нам точку из списка в окне Debug)
- LogCount - количество записей в логах. Это свойство включает ведение лога по прошедшим через точку останова событиям. Необходимо в тех случаях, когда события приходят настолько быстро, что изменения в окне отладки невозможно заметить визуально. Установим его значение в 20.

   После всех этих зменений схема будет выглядить следующим образом:

Add(Button,4165716,161,91)
{
Left=110
Top=50
link(onClick,12918180:doFor,[])
}
Add(For,12918180,217,91)
{
End=10
link(onEvent,4840112:doEvent,[])
}
Add(Label,12986552,315,91)
{
Left=180
Top=50
}
Add(Debug,4840112,280,91)
{
link(onEvent,12986552:doText,[])
}
   Запустите программу и нажмите кнопку Push. Текст элемента Label изменился на число 10. Перейдем к окну отладки и попробуем выяснить, что же происходило в схеме после нажатия кнопки и запуска цикла.
   В окне отладки присутствует только одна строка с заданным ранее именем onFor-doCaption. Далее идет колонка с именем Value - в ней выводится значение данных из потока, который прошел через точку останова. Следующий столбец Type - отображает тип прошедших данных. И наконец последний столбец - Count - показывается сколько всего событий прошло через точку останова с момента запуска приложения. Глядя на рисунок справа можно сказать следующее: событие цикла onFor произошло 11 раз, причем последнее из них вернуло в поток целочисленные данные со значением "10". А что же вернули в поток все предыдушие события элемента? Для ответа на этот вопрос как раз и нужен лог по событиям. Чтобы открыть его необходимо выделить строку в списке точек и нажать вторую слева кнопку "Show log". После чего на экране появится окно с содержимым лога примерно следующего содержания:

13:45:55 Type = 1 : 0
13:45:55 Type = 1 : 1
13:45:55 Type = 1 : 2
13:45:55 Type = 1 : 3
13:45:55 Type = 1 : 4
13:45:55 Type = 1 : 5
13:45:55 Type = 1 : 6
13:45:55 Type = 1 : 7
13:45:55 Type = 1 : 8
13:45:55 Type = 1 : 9
13:45:55 Type = 1 : 10
   Формат одной строки лога достаточно прост: сначала идет время прихода события, потом тип данных в потоке (1 – это Integer) и затем собственно данные. Т.е. глядя на этот список можно говорить о том, что событие onFor произошло 11 раз менее чем за 1 секунду и вернуло в поток число от 0 до 10 на каждое из событий соответственно. Т.е. элемент For выдает события onFor с данными в диапазоне от свойства Start=0 до свойства End=10 с шагом Step=1 при условии включения верхней границы диапазона IncludeEnd=True. Попробуйте поменять эти свойства и посмотреть, как изменяется поведение элемента.

   В заключение хотелось бы отметить, что изучение работы элемента не по его документации или примерам, а путем исследования событий через точки останова должно носить исключительно ознакомительный характер, поскольку часть элементов может работать иначе в зависимости от данных, которые поступили на тот или иной метод. Скажем, у все того же элемента For при включенном свойстве InData границы диапазона могут браться из потока, и если этот поток определяется пользователем, хранится в файле или берется из любого иного внешнего источника, то у вас там будет одно значение, а у пользователя может оказаться совершенно другое и количество итераций цикла, как следствие, может быть каким угодно.
BB-code статьи для вставки
Всего комментариев: 0
(комментарии к статье еще не добавлены)
Комментарий
...