ПОНЯТНО О Visual Basic NET (том 2)

Отладка программы


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

Сначала перечитайте, пожалуйста, материал про сообщения об ошибках в 1.3.8 и про пошаговый способ в 5.3.2.

Приступим. На Рис. 9.1 вы видите в окне кода в процессе отладки некую бессмысленную процедуру Button1_Click и несколько отладочных окон. Вот эта процедура:

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        Debug.WriteLine("Начало работы")

        Dim a As Integer = 20

        Dim b As Integer = 3

        Do Until b > a

            Debug.WriteLine(a & "         " & b)

            a = a - 2

            b = b + 1

        Loop

        Debug.WriteLine("Конец работы")



End Sub

Легко видеть, что выполнившись с начала до конца, эта процедура печатает в окне Output такую информацию:

Начало работы

20         3

18         4

16         5

14         6

12         7

10         8

Конец работы

Вообразим, что нас такая печать не устроила, мы создавали процедуру для того, чтобы было напечатано

Начало работы

20         3

18         4

Конец работы

Вообразим, что мы не можем сразу понять, как изменить программу, чтобы получилось то, что нам нужно. Ясно, что в программе где-то что-то надо исправить. Чтобы разобраться в случившемся и найти ошибку, мы затеяли отладку.

Что же мы делаем? Прежде всего мы обычным способом помещаем на экран окно Output. Затем мы ставим точку прерывания на заголовке процедуры и запускаем проект. Затем нажимаем на кнопку Button1 и проект прерывается на заголовке процедуры. Ну вот, теперь мы находимся в режиме прерывания. Теперь можно отлаживать.

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



Рис. 9.1
Окно Locals. Идем дальше. При помощи Debug ® Windows ® Locals мы вызываем на экран окно Locals (см. рисунок). Назначение окна Locals – показывать в режиме прерывания значения локальных переменных и других объектов выполняемой процедуры. (Локальные переменные – это переменные, объявленные внутри процедуры[†]). Столбец Name в окне Locals означает имя переменной или объекта. Столбец Value показывает нам их значение. К тому же в столбце Type вы можете видеть информацию о типе переменных и объектов.
После того, как проект прервался на заголовке процедуры, мы запускаем клавишей F11 пошаговый режим выполнения проекта (если VS настроена на профиль Visual Basic 6, то это будет клавиша F8). После нескольких нажатий на F11 окна Locals и Output принимают тот вид, что вы видите на рисунке. Правда, мы и без окна Locals в любой момент можем узнать значения a и b, просто поместив на них мышиный курсор. Однако применение окна Locals избавляет нас и от этих мизерных трудов.
Щелкните по плюсику слева от Me. Форма расскажет вам о текущих значениях своих свойств. Такие же плюсики вы видите у других объектов. Если в вашей процедуре имеются сложные переменные, например, массивы или структуры, щелкнув по плюсику рядом с ними, вы увидите значения всех их составных частей.
Если вы перейдете к выполнению другой процедуры, то в окне Locals будут видны уже именно ее локальные переменные.
Точки прерывания (Breakpoints). Когда программа большая или циклов много, жать на F11 приходится слишком часто. Но ведь и нужды-то в этом нет. Обычно вам интересно останавливаться не на каждой строке программы, а только на некоторых подозрительных, остальные можно выполнять и без остановки. VS позволяет вам задать такие строки – точки прерывания
(Breakpoints). Щелкните по вертикальной серой полосе в левой части окна кода против строки, на которой хотите прерывать выполнение программы. На полосе появится черная точка и вся строка будет выделена черным (все это описано в 5.3.2).
Щелкните также против всех нужных вам строк. Все они станут черными. Запустите проект обычным образом (кнопка Start или клавиша F5).  Дойдя до первой же точки прерывания, проект перейдет в режим прерывания. Продолжайте его работу клавишей F5. Проект будет останавливаться только на точках прерывания. Убираются точки прерывания так же, как и ставятся – щелчком мыши.


«Беги до курсора» – Run To Cursor. Это еще один удобный способ остановки в нужной вам строке. Щелкните правой клавишей мыши по нужной строке и в возникшем контекстном меню выберите команду Run To Cursor. При этом происходит вот что. Щелчок правой клавишей мыши ставит текстовый курсор в нужную строку, а команда Run To Cursor запускает выполнение. Программа будет выполняться до тех пор, пока не наткнется на строку с курсором. А теперь щелкните правой клавишей мыши в другой строке и в возникшем контекстном меню снова выберите команду Run To Cursor. Программа продолжит работу с того места, где остановилась, и будет выполняться до тех пор, пока не наткнется на строку с курсором. И так далее.
Переключаемся между способами прерывания. В процессе выполнения программы вы можете достаточно свободно переключаться между разными способами прерывания. Ставьте и убирайте точки прерывания, нажимайте то F11, то F5, бегите временами до курсора. VB будет вас слушаться. Это удобно.
Если вы  работаете в пошаговом режиме в какой-то процедуре, которая вызывает много других процедур, вам не интересных, то работайте не клавишей F11, а клавишей F10. При этом все другие процедуры будут проскакиваться мгновенно.
Окна Watch. Вообразим, что окно Locals не заставило нас поумнеть. Нам все кажется, что цикл должен был бы прерваться уже при значении b=5, а почему не прервался – непонятно. Чтобы разобраться, что к чему, нам хотелось бы в любой момент времени с удобством присматривать, правда или неправда, что b=5. Также нам хотелось бы в любой момент знать, правда или неправда, что b>a. То есть нам хотелось бы, чтобы вычислялись булевские выражения  b=5  и  b>a  и результаты в виде True или False были видны в окне. Окно Locals такой возможности не дает. Более широкие возможности – у окна Watch. Вызовем его так: Debug ® Windows ® Watch ® Watch1 (можно было вызвать и другие три окна Watch). Типичный вид этого окна при отладке другой программы вы можете видеть на Рис. 9.2.

Рис. 9.2
Его вид не отличается от окна Locals. Отличие – в возможностях. В столбец Name мы можем вводить имена каких угодно (а не только локальных) переменных и объектов. А также мы можем вводить туда какие угодно выражения. В столбце Value мы видим значения этих переменных и выражений. Если вы щелкнете по плюсику слева от Button1, то кнопка расскажет вам о текущих значениях своих свойств. Если в вашем проекте имеются сложные переменные, например, массивы или структуры, введите их имена в столбец Name и, щелкнув по плюсику рядом с ними, вы увидите значения всех их составных частей.


В нашем случае я ввел в окно Watch1 оба наших выражения: b=5 и b>a. На Рис. 9.1 вы видите значения этих выражений в тот момент выполнения проекта, когда b равно 5 и a равно 16.
Настройка точек прерывания. Окно Watch помогает неплохо. Но мы устали жать на F11. Чтобы не уставать, мы ставим точку прерывания на одну из строк в цикле, скажем, на Loop, и жмем уже на F5, а не на F11. Теперь выполнение останавливается реже – один раз на итерацию (выполнение цикла). Стало легче. Но это когда итераций мало. А если их штук 500?  500 раз нажимать на  F5 – тоже не подарок. В этом случае вам захочется найти более умные и быстрые средства отладки. И они есть. Рассмотрим их применительно к нашему случаю.
Хорошо бы наша программа исполнялась в своем обычном сверхбыстром режиме и проскакивала нашу точку прерывания без остановки, но каждый раз, однако, проверяя, выполняется ли некое условие, скажем, b=5. Оно по нашим подозрениям поначалу равно False, но затем в какой-то момент выполнения вроде бы станет равным True. Вот этот самый момент мы и хотим, чтобы VB поймал и тут же остановил программу.
Итак, нам нужен совсем другой способ остановки – хоть и на нужной строке, но не всегда, а только при выполнении заданного условия. Для этого точку прерывания, установленную на данной строке, нужно настроить.
Для настройки точки прерывания завершим выполнение проекта и перейдем в режим проектирования. Щелкнем правой клавишей мыши по точке прерывания и в возникшем контекстном меню выберем Breakpoint Properties. Возникнет окно настройки свойств точки прерывания (см. Рис. 9.3).

Рис. 9.3
В этом окне нас сейчас интересуют только кнопки Condition и Hit Count.
Condition. Нажав кнопку Condition, мы видим окно настройки условия для прерывания (Рис. 9.4).

Рис. 9.4
Вводим в поле наше условие (b=5). Затем – ОК. Теперь компьютер остановится на точке прерывания только тогда, когда будет выполнено условие. Этот момент остановки вы и видите на Рис. 9.1.
 Под полем для условия вы видите переключатель на два положения. Нижнее положение приказывает прерваться не при выполнении условия, а при любом изменении значения выражения, записанного в поле.


  Hit Count. Нажав кнопку Hit Count, мы видим окно настройки счетчика прерываний (Рис. 9.5).

Рис. 9.5
Его дело – останавливать компьютер на точке прерывания не всегда, когда позволяет условие, а еще реже. Как именно реже, определяет список из 4 способов. Важную роль играет число, которое вы вводите в поле справа. На рисунке введено число 3 и мы для определенности будем пояснять относительно него. Вот 4 способа:

break always
Останавливай всегда, когда позволяет условие, а если условия нет – то вообще всегда.
break when the hit count is equal to
Останавливай на 3-й раз и больше никогда
break when the hit count is a multiple of
Останавливай через каждые два раза на 3-й
break when the hit count is greater than or equal to
Останавливай на 3-й раз и после этого всегда

Окно Quick Watch. Кроме этих окон вы видите на Рис. 9.1 еще одно окно – Quick  Watch. Оно понадобилось вот для чего. Иногда в процессе работы в режиме прерывания вам захочется узнать, чему равно в настоящий момент значение того или иного выражения из процедуры, например a - 2. Вы, конечно, можете включить это выражение в окно Watch, но быстрее поступить так: Выделите нужное выражение в окне кода, как это сделано на рисунке, затем щелкните по выделенному выражению правой клавишей мыши и в возникшем контекстном меню выберите команду Quick Watch. Окно появляется уже с нужной информацией. Если вы захотите ввести это выражение в окно Watch, щелкните кнопку Add Watch.
Окно  Command Window-Immediate позволяет в режиме прерывания вычислять выражения, узнавать значения переменных и свойств объектов проекта, и, что самое пикантное, принудительно менять их.
Вызывается оно так: Debug ® Windows ® Immediate. Возникает окно с заголовком Command Window-Immediate. Не спутайте его с окном, имеющим заголовок Command Window, которое вызывается по-другому (View ® Other Windows ® Command Window) и не совсем вам подходит.
Пользуются этим окном так. Нужно в режиме прерывания вводить в него команды (вручную или скопировав из окна кода) и нажимать Enter. Тут же, в следующей строке вы будете видеть результат. Вот пример содержимого окна Command Window-Immediate (вводимые вами команды я выделил полужирным шрифтом):


?a
14
?a+10
24
?a<33
True
Debug.WriteLine(a & "    " & b)
14    6
a=1000
?a
1000
? textbox1.text
"TextBox1"
textbox1.text="Привет!"
? textbox1.text
"Привет!"
textbox1.BackColor=color.LightSeaGreen

Пояснения: Знак вопроса означает запрос значения переменной, свойства или выражения. Так, команда
?a
означает запрос на значение переменной a и получает результат 14.
Команда
Debug.WriteLine(a & "    " & b)
скопирована из окна кода и дала ожидаемый результат:
14    6
Команда
a=1000
принудительно меняет значение переменной a. То есть происходит прямое и неприкрытое вмешательство в святая-святых – работу программы. Но польза от этого для отладки есть. (Это еще ничего, предыдущие версии Visual Basic разрешали менять даже операторы программы в процессе выполнения. Представляете?! И тоже, кстати, не без пользы.)
Команда
? textbox1.text
узнает значение свойства объекта.
Команды
textbox1.text="Привет!"
и
textbox1.BackColor=color.LightSeaGreen
меняют свойства объекта.
Окно Command Window-Immediate не дает вам привычной свободы окна кода. Скорее оно похоже на командную строку с историей. Для навигации по окну вы можете пользоваться мышкой и на клавиатуре стрелками вверх-вниз. Нажатие клавиши Enter на любой промежуточной строке в этом окне отправляет эту строку вниз. Стрелки вверх-вниз не движут курсор, а «вспоминают» команды. Ничего, привыкнуть можно.
Окно Call Stack. Когда в программе содержится много взаимодействующих процедур, вам при отладке может быть совершенно необходимо разобраться в последовательности их выполнения. В этом случае вам поможет окно Call Stack, которое и покажет вам эту последовательность. Вызывается оно так: Debug ® Windows ® Call Stack.
Все описанные в этом разделе возможности отладки, а также некоторые другие, не описанные мной, приведены в меню Debug (отладка).

Содержание раздела