Назад | Начало урока | Вперед
Содержание

Глава 16

Через тернии к... работающей
программе

В этой главе ...

Представьте, что вы блуждаете по лабиринту и не можете найти выхода. Заряд батареи
заканчивается, и ваш фонарик вот-вот погаснет. Повсюду слышится непонятное
"клик, клик, клик...". Вы опускаете глаза и видите, что по колено стоите в кишащей массе
огромных тараканов!

Это может выглядеть как кошмарный сон, но примерно так чувствует себя программист, который
всю ночь не отрывался от компьютера и чем больше писал кодов, тем больше появлялось
ошибок— этих мерзких и противных программных тараканов. И в результате, когда на следующее
утро он попытался запустить написанную программу... кошмар! Ничего не работает.
Есть четыре варианта дальнейших действий.

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

В этой главе речь пойдет об использовании для корректировки программ отладчика Visual C++ .NET.

Вверх

Синтаксическин и логические ошибки

Как отмечалось в главе 6, синтаксические ошибки случаются тогда, когда компилятор не может "понять" написанный вами код. Например, если вы в слове вместо одной буквы набрали другую, пропустили часть команды либо неправильно использовали какую-то переменную или класс, все это будет воспринято как синтаксические ошибки. До тех пор пока в программе есть хоть одна синтаксическая ошибка, она не может быть выполнена, поскольку компилятор не сможет ее откомпилировать.

Кроме синтаксических, есть еще логические ошибки (программисты называют их bugs — жучки). Программа может быть написана на безупречном C++, но выполнять совершенно бессмысленные действия. Или она может работать, но несколько не так либо совсем не так, как было задумано. В таком случае в программе есть логические ошибки.

Рассмотрим, например, инструкцию по приготовлению печеной картошки.

  1. Взять картошку.
  2. Завернуть ее в фольгу.
  3. Положить в микроволновую печь на три часа.

Инструкции просты и без труда могут быть выполнены кем угодно. Синтаксических ошибок здесь нет. Но с другой стороны, если эти инструкции выполнить, микроволновая печь просто сгорит (черт с ней, с картошкой). Наверное, это не тот результат, который нужно было получить.

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

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

Вверх

Процесс отладки программы

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

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

В процессе отладки программы можно использовать несколько полезных инструментов.

Вверх

Отладчик плюс редактор – и все в наших руках

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

Процессы редактирования и отладки программы тесно связаны между собой. Иначе и быть не может, поскольку при отладке программы необходимо просматривать исходные коды, чтобы видеть, выполнение каких из них приводит к тем или иным результатам. Так как Visual C++ объединяет процессы редактирования и отладки, при отладке можно использовать любые возможности редактора кодов (такие, как прокрутка окна, разделение окна или поиск нужного слова). Вы можете даже при отладке сразу же вносить изменения в исходные коды.

Но не вся информация отображается непосредственно в окне редактора. Некоторые действия, связанные с отладкой программ, сопровождаются открытием специальных окон. Например, если вы захотите просмотреть значения переменных, для этого откроется отдельное окно Watch. (Более подробно это описывается несколько ниже в главе.)

Вверх

Остановись, мгновение!

Точки останова позволяют остановить выполнение программы в нужном месте. Предположим, например, что у вас есть подпрограмма, вычисляющая факториал числа. По какой-то причине возвращаемый ею результат всегда равен нулю. Чтобы определить, в чем заключается ошибка, можно установить точку останова в начале этой подпрограммы. Затем, когда вы запустите программу, ее выполнение будет остановлено в момент вызова процедуры, вычисляющей факториал, и вы сможете использовать все средства отладчика для определения, что именно в этой процедуре работает не так. Забегая вперед, скажем, что весь материал, изложенный далее в главе, посвящен решению подобных проблем.

Установить точку останова довольно просто. В окне редактора кодов щелкните правой кнопкой мыши в том месте, где нужно установить точку останова, и в открывшемся меню выберите команду Insert Breakpoint (Установить точку останова). Слева от выбранной строки появится значок точки останова. Ну хорошо, этим значком будет красный кружок, а не ромбик или что-то еще, но главное, чтобы вы поняли общую идею.

Совет:

Если вы установили точку останова и не видите слева от строки соответствующий значок, значит, у вас, скорее всего, отключена возможность отображения дополнительной информации на границе строк. Выберите команду Tools ^Options (Сервис^Параметры), чтобы открыть диалоговое окно Options (Параметры). В категории Text Editor/General (Редактор/Общие) выберите General (Общие) и затем опцию Selection Margin (Выделение на границе). Щелкните на кнопке ОК, и знак точки останова появится напротив выбранной строки.

Удаляется точка останова так же просто, как и устанавливается. В окне редактора кодов щелкните правой кнопкой мыши на строке, для которой установлена точка останова, и в открывшемся меню выберите команду Remove Breakpoint (Удалить точку останова). Расположенный напротив этой строки значок точки останова исчезнет с экрана.

Точки останова не исчезают после перезагрузки системы. Другими словами, если вы
установили точку останова и не удаляли ее, а позже вновь открыли этот же проект,
созданная точка останова по-прежнему будет на своем месте. Это очень удобно, поскольку процесс отладки программы может затянуться на какое-то время и вы можете прерывать его на то, чтобы, например, поспать, перекусить или побродить по Internet. Затем, когда вы снова вернетесь к отладке программы, вам не придется заново восстанавливать всю картину и расставлять прежние точки останова. Однако с другой стороны, если программа уже будет работать так, как нужно, но вы забудете убрать какие-то точки останова, то она потом непременно выдаст вам парочку "сюрпризов". (Выполнение программы будет прерываться каждый раз, когда в кодах будут встречаться точки останова.) Если вы не уверены, все ли точки останова удалены, выберите команду Debug^Windows^Breakpoints (Отладка^Окна1^Точки останова). В результате откроется окно, в котором будут показаны все существующие на данный момент точки останова.

Вверх

Шаг за шагом: движение к цели

После того как точка останова достигнута, самое время проследить, как будет выполняться каждая последующая инструкция. Сделать это можно, выполняя по одной строке кода за раз. Такие действия называются пошаговым выполнением программы.
Есть два варианта: использовать команду Step Into (Пошаговое выполнение) либо команду Step Over (Пошаговое выполнение с перешагиванием через процедуры). Если в процессе использования команды Step Into программа вызывает какую-то функцию, все ее коды также выполняются пошагово. Если программа вызывает функцию в процессе использования команды Step Over, все коды функции выполняются сразу же, без остановки на каждом шаге.

Команду Step Into следует использовать в том случае, если какая-то часть программы работает не так, как нужно, но вы не уверены, содержится ли ошибка в этом фрагменте кода или в той функции, которая при этом вызывается. Команда Step Over используется в том случае, если проверяемые коды должны выполняться пошагово, а вызываемые при этом функции — как единое целое.
Рассмотрим это на таком примере:

foo = MyRoot(x);
foo = foo + 1;

Если вы точно знаете, что функция MyRoot работает правильно, и хотите только проверить, как будет выполнена строка foo+l, можете использовать команду Step Over. Первая строка будет выполнена за один шаг (включая все инструкции, из которых состоит функция MyRoot), и затем на втором шаге будет выполнена строка foo=f o o + l .

Если вы сомневаетесь в правильности выполнения функции MyRoot, используйте команду Step into. При этом, выполняя первую строку, вы перейдете к первой строке функции MyRoot. Затем пошагово, одна за другой, будут выполняться все строки этой функции, и если вам повезет, вы найдете там свою ошибку.
В процессе пошагового выполнения программы слева, напротив строки, которая должна выполниться на следующем шаге, будет отображаться желтая стрелка. Если для этой строки определена точка останова, стрелка будет отображаться сверху над красным кружком.

Если при пошаговом выполнении программы вы не видите желтой стрелки, значит, у вас, скорее всего, отключена возможность отображения дополнительной информации на границе строк. Выберите команду Tools1^ Options, чтобы открыть диалоговое окно Options. В категории Text Editor/General выберите General и затем опцию Selection Margin. Щелкните на кнопке ОК, и желтая стрелка появится на экране.
Для пошагового выполнения с перешагиванием через процедуры нажимайте клавишу
или щелкайте на кнопке Step Over панели Debug (Отладка), показанной на рис. 16.1.
Если вызываемые функции также должны выполняться пошагово, нажимайте клавишу
или щелкайте на кнопке Step Into.

Рис. 16.1. На панели Debug расположены

кнопки, управляющие процессом выполнения программы
Обратите внимание, что команды Step Into и Step Over могут быть использованы без
предварительного определения точек останова. Если вы сделаете это, пошаговое выполнение будет начато с самой первой строки программы.

Вверх

Посмотрим, что получилось

Занимаясь отладкой программы, очень важно знать, правильный ли результат возвращает формула, какое значение имеет переменная или что сохранено в качестве элемента массива.
Visual C++ предлагает несколько способов просмотра значений переменных и получаемых при обработке выражений результатов.
Окно Autos (Автоматическое) открывается автоматически, когда вы приступаете к отладке программы (рис. 16.2). В нем отображаются названия и значения переменных, которые используются в текущем и предыдущем выражениях. Лично вам не нужно указывать имена переменных — они сами и их значения отображаются автоматически, по мере того как вы переходите от одной строки программы к другой.

РИС. 16.2. В окне Autos отображаются имена и значения переменных, используемых в предыдущем и текущем выражениях Также при отладке программы автоматически отображается окно Locals (Локальные), показанное на рис. 16.3. Как и в окне Autos, в нем автоматически отображаются названия переменных и их значения.
Но здесь уже отображаются все локальные переменные той функции, коды которой выполняются в данный момент (т.е. переменные, объявленные внутри этой
функции).

Рис. 16.3. В окне Locals отображаются имена и значения всех локальных переменных
Окна Autos и Locals предоставляют полезную информацию, но, поскольку они сами определяют, значения каких переменных должны отображаться, иногда они не очень удобны.
Но в этом нет ничего страшного, так как в Visual C++ есть другие средства для контроля за значениями переменных. В окне Watch (Просмотр) вы можете сами указать, какие именно значения вас интересуют. Всего есть четыре окна Watch, пронумерованных от Watchi до Watch4, что позволяет выделить несколько наборов переменных и выражений, значения которых вы хотите проконтролировать.
Чтобы просмотреть значение какого-либо объекта, используя окно Watch, выполните
следующее.

  1. В окне Watch щелкните на пустой строке в колонке Name (Имя).
  2. Наберите имя объекта, значение которого вы хотите видеть.
  3. Нажмите клавишу .

Каждый раз, когда значение объекта изменяется, информация в окне Watch обновляется. Например, на рис. 16.4 показано окно Watch со значениями трех числовых переменных. Как только значение переменной nNumber, nResult или i изменится, окно Watch будет обновлено.

Рис. 16.4. Окно Watch позволяет видеть, как изменяются значения интересующих
вас переменных в процессе выполнения программы

Не нравится значение — измените его

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

  1. Выделите переменную, значение которой вы хотите изменить.
  2. Выделите значение этой переменной.
  3. Наберите новое значение.
  4. Нажмите клавишу .

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

Вверх

Торопитесь? Нет проблем!

Visual C++ позволяет просматривать значения переменных и выражений без необходимости добавления их в окно Watch, используя для этого средство QuickWatch.
Чтобы использовать QuickWatCh для просмотра значения какого-либо объекта, выполните в окне редактора следующие действия: щелкните правой кнопкой мыши на названии интересующего вас элемента и выберите в открывшемся меню команду QuickWatch. Откроется диалоговое окно QuickWatch (рис. 16.5). Затем, если вы захотите перенести выбранный объект из окна QuickWatch в окно Watch, просто щелкните на кнопке Add Watch (Добавить в окно Watch).

Рис. 16.5. Значения переменных можно просматривать, не добавляя их в окно Watch

Очень торопитесь?

Средства Watch и QuickWatch удобны, но все же, чтобы их использовать, вам придется несколько раз щелкнуть кнопкой мыши. Представим, что вы этого делать не хотите. Тогда Visual C++ может предложить другое средство, которое называется DataTips (Подсказка). Оно позволяет увидеть значение переменной без единого щелчка кнопкой мыши.

Чтобы просмотреть значение переменной, используя средство DataTips, выполните следующее.

  1. В окне редактора поместите курсор над той переменной, значение которой вы
    хотите увидеть.
  2. Подождите полсекунды.
    Рядом с курсором появится подсказка, в которой будет показано текущее значение этой переменной (рис. 16.6).

//// Материал пропущен

Рис. 16.6. DataTips показывает значения переменных без каких-либо усилий
с вашей стороны

Вверх

Генеральная уборка

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

Итак, приступим

Начнем с того, что создадим новую управляемую программу C++. Код этой программы
показан ниже. Как и одна из рассмотренных ранее программ, эта программа отображает на экране факториал указанного пользователем числа.


#include "stdafx.h"
#using <mscorlib.dll>
using manespace System;

//Функция возвращает факториал числа
int Factorial(int nNumber)
{

int nResult = nNumber;
int i; //Переменная для отсчета итераций
//Цикл, на каждой итерации которого общий результат
//умножается на значение переменной i
for (i=0; i<= nNumber; i++)
{
nResult *= i;
}
//Возвращение результата
return nResult;
}

//Функция проект пользователя набрать число,
//а затем возвращает это число как результат
int GetNumber()
{

int nNumber;
Console::WriteLine(3"Введите число");
nNumber = Int32::Parse(Console::ReadLine()
return nNumber;
}

//С этой точки начинается выполнение программы
#ifdef _UNICODE
int main (void)
#else
int main(void)
#endif
{

int nNumber;
//Получение чисел от пользователя до тех пор,
//пока он не наберет число О
while (nNumber = GetNumber())
{
//Отображение значения факториала для указанного
//числа. При этом используется значение,
//возвращаемое функцией Factorial
Console::WriteLine(S"Факториал числа {0} равен {}", nNumber.ToString(), Factorial(nNumber).ToString() //Ожидание, пока пользователь не остановит //выполнение программы Console::WriteLine(S"Нажмите клавишу Enter, чтобы
остановить выполнение программы");
Console::ReadLine() ;
return 0;
}
}

Если процесс создания управляемых проектов на C++ вызывает у вас затруднения, вернитесь к главе 3.

А теперь попытайтесь несколько раз подряд выполнить эту программу.

  1. Щелкните на кнопке Start или выберите команду Debug<=>Start (Отладка^Начать).
  2. Наберите число и нажмите клавишу .
  3. Посмотрите на полученный результат.

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

Так где же ошибка?

Попытаемся определить, из-за чего программа не работает (точнее, работает, но не так, как нужно). В кодах для получения числа от пользователя вроде бы нет ничего подозрительного;

Console::WriteLine(S"Введите число");
nNumber = Int32::Parse(Console::ReadLine());
return nNumber;

Выполнять эти инструкции пошагово, по-видимому, нет необходимости.
Вместо этого сосредоточим внимание на работе функции Factorial .
Почему именно эта функция? Потому что это единственная функция в программе, выполняющая действия, понимание которых может вызвать у вас затруднения. Отладку более сложных программ обычно производят небольшими частями — по одной функции или объекту за раз. Если вы убедитесь, что отдельные небольшие части программы работают правильно, значит, коды, в которых эти части объединяются, также будут работать правильно. Таким образом, вы всегда можете сосредоточиться на небольших, легких для понимания фрагментах программы. Иногда этот метод называют структурной проверкой (structured testing).

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

  1. Прокрутите окно редактора, для того чтобы увидеть коды функции
    Factorial .
    Коды этой функции набраны в самом начале программы.
  2. Щелкните правой кнопкой мыши на строке int Factorial(int nNumber) и
    выберите команду Insert Breakpoint.

Напротив этой строки отобразится символ точки останова подобно тому, как показа-
но на рис. 16.7.

Теперь запустите программу.

  1. Щелкните на кнопке Start.
    Программа начнет работать, и на экране появится надпись, предлагающая ввести
    число.
  2. Наберите число.
    Далее программа должна вызвать функцию Factorial . Это значит, что точка оста-
    нова будет достигнута, в результате чего откроется окно отладчика. Напротив строки, которая должна будет выполнятся следующей, вы увидите желтую стрелку (рис. 16.8).
Теперь можно приступить к пошаговому выполнению функции Factorial и постараться определить, где именно прячется ошибка. Поскольку точно известно, что функция возвращает неправильный результат, а сам вычисляемый результат сохраняется как значение переменной nResult, вам нужно проследить, как значения этой переменной изменяются в процессе выполнения функции. Таким образом, вы рано или поздно поймете, почему функция каждый раз возвращает нулевое значение. Для просмотра значения переменной можно использовать окно Locals или подсказку DataTip. Либо можно воспользоваться окном Watch, для чего выполните следующее.

  1. В окне Watch щелкните на пустой строке в колонке Name.
  2. Наберите nResult.
  3. Нажмите клавишу .
Можно также воспользоваться средством QuickWatch.
  1. В окне редактора щелкните правой кнопкой мыши на переменной nResult и в
    открывшемся меню выберите команду QuickWatch.
  2. В окне QuickWatch щелкните на кнопке Add Watch.
    После этого нижняя часть экрана будет выглядеть приблизительно так, как показано
    на рис. 16.9.
  3. Проследите за выполнением этой функции, щелкнув несколько раз на кнопке
    Step Over.

Информация о значении переменной nResult, отображаемая в окне Watch, будет
обновляться каждый раз при изменении этого значения.
В результате вы увидите, что сразу же после выполнения инструкции nResult *= i
значение переменной nResult станет нулевым.

Более того, по мере выполнения программы это значение никогда не будет изменяться. Как вы узнаете, что значение переменной nResult равно нулю? Очень просто: для этого существует окно Watch (или Locals, или QuickWatch, или подсказка DataTip).

Если вы используете окно Watch, то оно постоянно будет выглядеть так, как показано на рис. 16.10.
Рис. 16.7.0 наличии точки останова свидетельствует красный кружок, отображаемый слева от строки

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


Рис. 16.9. В процессе отладки программы в окне Watch постоянно будет отобра-
жаться текущее значение переменной nResul t

Рис. 16.10. Значение переменной nRes ult постоянно будет оставаться нулевым

Поскольку переменная nResult принимает нулевое значение именно в результате выполнения цикла for, вы точно можете сказать, что ошибку нужно искать именно там. Поэтому нужно более тщательно проанализировать коды этого цикла. Так как первая (и единственная) строка цикла умножает значение переменной nResult на значение переменной i, возможно, что-то не в порядке с переменной i. Если вы посмотрите на начало цикла for, то увидите, что значения переменной i изменяются от нуля до числа, введенного пользователем:

for (i=0; i<=nNumber; i++)
Это значит, что на первой итерации значение переменной i равно нулю. А поскольку
умножение на ноль всегда дает нулевой результат, после выполнение инструкции
nResult *= i значение переменной nResult становится нулевым и более не изменяется. Вот в чем проблема!

Что теперь?

Ошибка содержится в цикле for. Чтобы определить это, вам пришлось пошагово выполнять часть кодов программы, следить за изменением значения переменной nResult, анализировать работу кодов, после выполнения которых переменная nResult получает нулевое значение. В результате вы обнаружили, что проблему можно устранить, если переменная цикла будет изменяться не от нуля до п, а от единицы до n.

Теперь исправьте код прямо в окне редактора.

  1. Щелкните в окне редактора.
    Это окно станет активным.
  2. Найдите следующую строку:
    fcr (i=0; i<=nNumber; i++)
  3. Измените ее так, как показано ниже.
    fcr (i=l; i<=nNumber; i++)
    После этого нужно опять запустить программу, чтобы убедиться,
    что теперь она работает правильно.
  4. Выберите команду Debug->Stop Debugging (Отладка->Остановить отладку).
    Выполнение программы будет остановлено. (До этого ее выполнение было остановлено на
    промежуточной стадии, так как ранее вы установили точку останова.)
  5. Щелкните на кнопке Build (Построить).
    Программа будет откомпилирована.
  6. Щелкните на кнопке Start (Запустить).
    Программа снова будет запущена на выполнение.

Обратите внимание, что для завершения выполнения программы шаг 4 не обязателен — можно просто щелкнуть на кнопке Build. Отладчик знает, что в коды программы были внесены изменения, поэтому он спросит, хотите ли вы остановить отладку программы. Чтобы внесенные изменения вступили в силу, программа должна быть заново откомпилирована, поэтому щелкните на кнопке Yes. Отладка будет прекращена, а программа заново откомпилирована. После этого можете щелкнуть на кнопке Start, чтобы запустить программу снова.

Когда появится сообщение с просьбой ввести число, наберите, например, число 5 и посмотрите, как поведет себя программа. Переменная nResult больше не будет принимать нулевое значение, благодаря чему можно решить, что теперь программа работает правильно.

Но в программе по-прежнему есть ошибка

Минуточку! Если вы продолжите пошаговое выполнение программы, то увидите, что не
все так хорошо, как хотелось бы. Что-то уж слишком быстро увеличивается значение переменной nResult.
Как и прежде, проблемы начинаются уже с первой итерации. В момент, когда вы переходите к выполнению цикла for, значение переменной nResult уже равно числу 5. На следующей итерации оно становится равным числу 10, затем числу 20 и т.д. Следя за этими изменениями в окне Watch, неизбежно приходим к выводу, что нужно заново разобраться в том, какое начальное значение присваивается этой переменной и каким образом оно потом изменяется.

Почему уже на первой итерации переменная nResult имеет значение 5? Еще раз подумайте о том, как программа должна работать, и сравните это с тем, что она делает на самом деле. (Точнее, нужно сравнить, что вы хотите от программы и какие инструкции вы оставили ей в действительности.) Чтобы вычислить факториал, нужно начать со значения переменной nResult, равного числу 1. затем умножить его на 2, затем на 3 и т.д. Проверим, так ли это было указано программе.

Если вы посмотрите на самые первые строки функции Factorial , то увидите, что переменная nResult объявляется и инициализируется следующим образом:
int nResult = nNumber;
Это неверно, и вот почему. Допустим, вам нужно вычислить факториал числа 5. Выполнение функции начинается с того, что переменной nResult присваивается значение 5. Затем оно умножается на число 1, потом на 2 и т.д. Таким образом получается результат, вычисленный как 5 x 1 x 2 3 x 4 x 5 вместо 1 x 2 x 3 x 4 x 5 . Теперь становится понятно, что начальное значение переменной nResult должно быть равным числу 1.

Устранение ошибки

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

  1. Щелкните в окне редактора.
    Окно редактора станет активным.
  2. Прокрутите окно редактора, чтобы найти строку
    int nResult = nNumber;
  3. Внесите в эту строку следующую коррективу:
    int nResult = 1;
  4. Щелкните на кнопке Build.
  5. В ответ на вопрос, действительно ли вы хотите остановить процесс отладки
    программы, щелкните на кнопке Yes.
    Программа будет откомпилирована.
  6. Щелкните на кнопке Start.

Программа вновь будет запущена на выполнение.
Вы можете быть довольны проделанной работой, поскольку теперь программа будет работать правильно. Например, если на запрос программы набрать число 6, то возвращен будет именно тот результат, который действительно соответствует факториалу числа 6 (рис. 16.11).

Рис. 16.11. Программа работает правильно

Последние штрихи
Теперь нужно удалить из программы точку останова и отменить отображение значения
переменной в окне Watch (если вы использовали для просмотра значения именно это окно).
Чтобы удалить точку останова, выполните ряд действий.
  1. Выберите команду Debug^Windows^BreakPoints (Отладка->Окна->Точки Останова).
    Откроется окно, в котором будет показан список всех установленных для программы
    точек останова (рис. 16.12).

Рис. /б. 12. В этом окне можно увидеть список всех точек останова, которые есть
в программе

  1. Выделите точку останова, которую хотите удалить.
  2. Щелкните на кнопке Delete (Удалить).
    Выделенная на втором шаге точка останова прекратит свое существование.

(Щелкните на кнопке Clear All Breakpoints (Удалить все точки останова), если хо-
тите удалить сразу все точки останова, показанные в окне Breakpoints.)
Отменить отображение значений переменных в окне Watch несколько сложнее, так как
получить доступ к этому окну можно только во время отладки программы.
  1. Щелкните на кнопке Step Into или нажмите клавишу .
    Будет запущен процесс пошагового выполнения программы, и на экране отобразится
    окно Watch.
  2. В окне Watch щелкните правой кнопкой мыши на названии переменной, ото-
    бражение значения которой нужно отменить, и в открывшемся меню выберите
    команду Delete Watch (Удалить из окна).
  3. Выберите команду DebugOStop Debugging (Отладка О Остановить отладку),

Чтобы завершить выполнение программы.
Теперь, когда вы снова запустите программу, ее выполнение не будет прерываться никакими точками останова. (Если не верите, можете проверить сами.)
Как видите, процесс отладки программы вовсе не сложен. Правда, нужно приобрести некоторый опыт, чтобы научиться быстро определять, в чем именно кроется ошибка.
Чем больше вы будете программировать, тем лучше у вас это будет получаться.

Вообще говоря, отладчик может предоставить вам множество дополнительных возможностей. С его помощью можно, например, просмотреть значения регистра CPU, увидеть коды ассемблера, генерируемые компилятором, установить условные точки останова. Чтобы узнать больше о возможностях отладчика, поэкспериментируйте с командами меню Debug или просмотрите статьи об использовании отладчика, которые можно найти в справочной системе Visual C++.


Назад | Начало урока | Вверх | Вперед
Содержание