11829

Отладка программ в интегрированной среде Microsoft Visual C++ 2008

Лабораторная работа

Информатика, кибернетика и программирование

Лабораторная работа №9. Отладка программ в интегрированной среде Microsoft Visual C 2008 1 Цель и порядок работы Цель работы – изучить инструментальные средства и возможности отладки программ в интегрированной среде Microsoft Visual C 2008 Visual Studio 2008. Порядок выполнения работы...

Русский

2013-04-12

189.5 KB

64 чел.


Лабораторная работа №9. Отладка программ в интегрированной среде Microsoft Visual C++ 2008

1 Цель и порядок работы

Цель работы – изучить инструментальные средства и возможности отладки программ в интегрированной среде Microsoft Visual C++ 2008 (Visual Studio 2008).

Порядок выполнения работы:

  •  ознакомиться с описанием лабораторной работы;
  •  получить задание у преподавателя, согласно своему варианту;
  •  написать программу и отладить ее на ЭВМ;
  •  оформить отчет.

2 Краткая теория

Интегрированная интерактивная среда разработки программ Microsoft Visual C++ 2008 (IDE) включает в себя ряд средств, облегчающих процесс нахождения ошибок в программе, которые не позволяют ей корректно работать.

2.1 Понятие отладки

Отладка – это процесс поиска и исправления ошибок в программе, препятствующих корректной работе программы.

Отладка программы является одним из наиболее важных и трудоемких этапов разработки. Трудоемкость и эффективность отладки напрямую зависит от способа отладки и от средств языка программирования.

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

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

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

  •  программируйте с постепенным наращиванием. При возможности кодируйте и отлаживайте программу небольшими секциями. Прорабатывайте каждую секцию до конца прежде чем переходить к следующей;
  •  разбивайте программу на части: модули, процедуры, функции. Избегайте построения функций, размер которых больше 25-30 строк, в противном случае разбивайте их на несколько меньших по размеру функций;
  •  старайтесь передавать информацию только через параметры, вместо использования глобальных переменных внутри процедур и функций. Это поможет Вам избежать побочных явлений и облегчит отладку программы, так как Вы сможете легко прослеживать всю информацию, входящую и выходящую из заданной процедуры или функции;
  •  не торопитесь. Сосредоточьте действия на том, чтобы программа работала правильно, прежде чем предпринимать шаги по ускорению ее работы.

2.2 Разновидности ошибок

Существует три основных типа ошибок: ошибки этапа компиляции, ошибки этапа выполнения и логические ошибки.

2.2.1 Ошибки этапа компиляции

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

Наиболее общей причиной ошибок этапа компиляции являются ошибки набора (опечатки), пропущенные точки с запятой, ссылки на неописанные переменные, передача неверного числа (или типа) параметров функции и присваивание переменной значений неверного типа.

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

2.2.2 Ошибки этапа выполнения

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

Когда Visual C++ обнаруживает такую ошибку, он завершает выполнение и выводит окно с сообщением о типе ошибки и адресом инструкции, в которой она произошла (см. рисунок 10.1).

Рисунок 10.1 – Окно ошибки времени выполнения

2.2.3 Логические ошибки

Логические ошибки – это ошибки проектирования и реализации программы. То есть, все операторы допустимы и что-то делают, но не то, что предполагалось. Эти ошибки часто трудно отследить, поскольку IDE не может найти их автоматически, как синтаксические и семантические ошибки. К счастью, IDE включает в себя средства отладки, помогающие найти логические ошибки.

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

2.3 Методы отладки

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

2.3.1 Установка точки прерывания

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

Чтобы задать точку прерывания перед некоторым оператором, необходимо установить перед ним текстовый курсор и нажать клавишу F9 или кликнуть мышью на левом боковом поле окна редактирования напротив оператора. Точка прерывания обозначается в виде красного кружка на левом поле окна редактирования (см. рисунок 10.2). Повторное действие (щелчок на указанной кнопке или нажатие F9) снимает точку прерывания. В программе может быть несколько точек прерывания.

Для просмотра всех точек остановки необходимо выбрать пункт Debug | Windows | Breakpoints или нажать комбинацию клавиш Ctrl+Alt+B.

Рисунок 10.2 – Окно редактора с установленной точкой прерывания

2.3.2 Выполнение программы до точки прерывания

Программа запускается в отладочном режиме с помощью команды Debug | Start Debugging (или нажатием клавиши F5).

В результате код программы выполняется до строки, на которой установлена точка прерывания. Затем программа останавливается и отображает в окне Editor ту
часть кода, где находится точка прерывания, причем желтая стрелка на левом поле
указывает на строку (см. рисунок 10.2), которая будет выполняться на следующем шаге отладки.

2.3.3 Прекращение отладки

В ходе сеанса отладки иногда желательно начать все сначала. Выбор команды Debug | Stop Debugging или нажатие клавиши Shift+F5 приведет к полному сбросу, так что выполнение по шагам, или трассировка прекратится.

2.3.4 Пошаговое выполнение программы и трассировка

Команды выполнения по шагам Step Over (клавиша F10) и трассировки Trace Into (клавиша F11) меню Debug дают возможность построчного выполнения программы. Единственное отличие выполнения по шагам и трассировки состоит в том, как они работают с вызовами функций.

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

Нажимая клавишу F10, можно выполнять один оператор программы за другим. Предположим, что при пошаговом выполнении программы вы дошли до строки, в которой вызывается некоторая функция func1(). Если вы хотите пройти через код вызываемой функции, то надо нажать клавишу F11, а если внутренняя работа функции вас не интересует, а интересен только результат ее выполнения, то надо нажать клавишу F10.

Допустим, что вы вошли в код функции funcl(), нажав клавишу F11, но через несколько строк решили выйти из него, т.е. продолжить отладку после возврата из функции. В этом случае надо нажать клавиши Shift+F11 или выбрать пункт Debug | Step Out.

2.3.5 Выполнение программы до курсора

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

Существует возможность пропустить пошаговое выполнение некоторого куска программы: установите текстовый курсор в нужное место программы и нажмите клавиши Ctrl+F10. Программа будет выполнена до курсора и остановится в данной точке ожидая дальнейших действий пользователя.

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

Чтобы продолжить дальнейшее выполнение программы без пошагового режима нажмите F5.

2.3.6 Отслеживание значений переменных во время выполнения программы

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

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

Чтобы узнать значение переменной задержите над ней указатель мыши. Рядом с именем переменной на экране появляется подсказка со значением этой переменной.

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

Помимо экранной подсказки, переменные со своим значением отображается в окне Locals, расположенном в левом нижнем углу экрана (см. рисунок 10.3). В этом окне приведены значения последних переменных, с которыми работал Visual C++. Кроме этого, в окне «Watch 1» (которое находится также в левом нижнем углу, но на другой вкладке) можно задать имя любой переменной, за значениями которой вы хотите понаблюдать.

Также можно добавить переменную в список просмотра «Watch 1» нажав правую кнопку мыши над именем переменой и выбрав пункт «Add Watch». Кроме этого в окне просмотра «Watch 1» можно добавлять или удалять отслеживаемые элементы. В этом диалоговом окне можно проверять переменные и выражения и изменять значения любых переменных, включая строки, указатели, элементы массива и поля записей, что позволяет проверить реакцию программы на различные условия.

Рисунок 10.3 – Окно редактора и список отслеживаемых переменных

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

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

2.3.7 Создание условной точки останова

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

Location – место остановки (строка  и модуль для остановки);

Condition – проверка условие изменения (на равенство какому-либо значению или на изменение значения);

Hit Count – проверка на счетчик проходов;

Filter – комбинация нескольких условий для значений переменной;

When Hit – задает действия при возникновении остановки.

Рисунок 10.4 – Дополнительные условия для точек остановки

2.4 Работа с отладчиком

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

2.4.1 Выполнение программы по шагам без захода в функцию

Это простейший способ выполнения программы по элементарным фрагментам. Выбор команды Debug | Step Over или нажатие клавиши F10 вызывает выполнение отладчиком всего кода в операторе, указанном строкой выполнения, включая любые вызываемые на ней процедуры или функции, пока управление не вернется обратно к программисту. После этого строка выполнения указывает следующий выполняемый оператор.

Возьмем следующий пример программы.

Пример 1 – Простая программа, выполняемая по шагам.

#include "stdafx.h"

#include <iostream>

using namespace std;

int sqr(int x)

{                                              //10

  int q = x*x;                                //11

   return q;                                  //12

}                                              //13

void main()

{                                              //0

  const int N = 10;                           //1

  int a[N] = {5, 2, 7, -9, 4, 8, -1, 0, 3, 6};//2

  //найдем сумму квадратов                    //3

  //положительных элементов массива           //4

  int s = 0;                                  //5

  for (int i = 0; i < N; i++)                 //6

      if (a[i] > 0) s += sqr(a[i]);           //7

  cout << s << endl;                          //8

  return;                                     //9

}

Если нажать клавишу F10, то строка выполнения перемещается на фигурную скобку в начале программы (строка 0), поскольку это первое, что выполняется в программе. Второе нажатие клавиши F10 перемещает строку выполнения вниз до оператора объявления константы размерности массива N на следующей строке (строка 1). После этого нажатие F10 переводит указатель к строке с объявлением массива и его инициализации (строка 2). Далее, при нажатии F10, строки 3 и 4 будут пропущены, так как они состоят только из комментариев и указатель переместится к строке 5. В ней производится объявление переменной для хранения суммы квадратов элементов массива s и ее инициализация нулем.

После этого нажатие F10 вызывает начало выполнения цикла for. Первое нажатие инициализирует переменную i, и указатель переходит к строке 7. Далее нажатие F10 приводит к выполнению оператора if и указатель переходит на строку 8. Однако далее управление будет передано обратно на строку 6, так как цикл еще не завершен.

Обратите внимание, что в окне Locals выводятся значения счетчика i, максимального элемента m, размерности массива N и сам массив a.

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

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

Если необходимо видеть подробности, то в пример нужно внести следующее простое изменение:

Пример 2 – Модифицированная программа, для лучшего выполнения по шагам

#include "stdafx.h"

#include <iostream>

using namespace std;

int sqr(int x)

{                                              //10

  int q = x*x;                                //11

   return q;                                  //12

}                                              //13

void main()

{                                              //0

  const int N = 10;                           //1

  int a[N] = {5, 2, 7, -9, 4, 8, -1, 0, 3, 6};//2

  //найдем сумму квадратов                    //3

  //положительных элементов массива           //4

  int s = 0;                                  //5

  for (int i = 0; i < N; i++)                 //6

      if (a[i] > 0)                           //7.0

         s += sqr(a[i]);                      //7.1

  cout << s << endl;                          //8

  return;                                     //9

}

Если теперь нажимать клавишу F10, то указатель после строка 7.0 будет при выполнении условия переходить на строку 7.1, а при не выполнении на строку 8.

2.4.2 Выполнение программы по шагам с заходом в функцию (трассировка)

Чтобы выполнить трассировку кода, необходимо выбрать команду Debug | Trace Into или нажать клавишу F11.

Первое нажатие на F11 также передает управление на фигурную скобку основной программы (строка 0). Повторные нажатия F11 снова перемещают строку управления на теже операторы, что и F10, пока мы не доходим до строки 7.1. После этого нажатие клавиши F11 трассирует вызов функции sqr – строка выполнения перемещается на фигурную скобку в блоке функции (строка 10). Если продолжать нажимать F11, строка выполнения перемещается по функции, а затем, когда дойдет до оператора return (при этом указатель будет располагаться напротив закрывающей фигурной скобки), возвращается к оператору вызова.

Следует обратить внимание на то, что трассировке подвержены и функции стандартных библиотек. Так, например, при выводе на экран s при помощи стандартного потока cout будет произведена трассировка функции вывод. Во избежание данного поведения необходимо использовать пошаговое выполнение (Step Over) по клавише F10, либо нажимать Shift + F11 для выхода из трассируемой функции.

3 Контрольные вопросы

  1.  Что такое отладка?
  2.  Для чего предназначена отладка?
  3.  Какие разновидности  ошибок существуют?
  4.  Какие средства отладки предоставляет среда разработки MS Visual C++?
  5.  Что такое точка остановки (breakpoint)?
  6.  Какие дополнительные условия можно устанавливать в точке остановки?
  7.  Какие возможности существуют для слежения за значениями переменных во время отладки?
  8.  Как изменить значение переменной?
  9.  Какие горячие клавиши для работы с отдатчиком вы знаете?

4 Задание

  1.  Выполнить задание  в соответствии с пунктом 5.1.
  2.  Выполнить задание  в соответствии с пунктом 5.2.
  3.  Оформить отчёт.

5 Задание для выполнения работы

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

Например:

  const int N = 10;                           //1

  int a[N] = {5, 2, 7, -9, 4, 8, -1, 0, 3, 6};//2

Последовательность выполнения:

2: a = {5, 2, 7, 9, 4, 8, -1, 0, 3, 6}

5: i = 0

6: i = 0, s = 25

5.1 Часть первая

  1.  Набрать программу примера 1 (раздел 2.4.1)
  2.  Выполнить программу по шагам, фиксируя в отчете, в строке с каким номером находится строка выполнения при каждом нажатии на F10.
  3.  Внести в программу изменения в соответствии с примером 2.
  4.  Выполнить задание пункта 2.
  5.  Выполнить трассировку исходной программы примера 3 (раздел 2.4.2), фиксируя в отчете, в строке с каким номером находится строка выполнения при каждом нажатии на F11.

5.2 Часть вторая

  1.  Набрать и откомпилировать следующую программу:

#include "stdafx.h"

#include <iostream>

using namespace std;

int sum(int *x, const int N)

{

  int s = 0;

  for (int i = 0; i < N ; i++)

      s += x[i];

   return s;

}

void main()

{

  const int N = 10;

  int a[N] = {1, 3, -5, 0, 4, 6, -1, 9, 3, 2};

  //найдем максимальный элемент массива

  int m = a[0];

  for (int i = 1; i < N; i++)

      if (m < a[i])

          m = a[i];

  cout << m << endl;

  //найдем сумму элементов массива

  int s;

  s = sum(a, N);

  cout << s << endl;

  int z = s / m;

  int k = 0;

  for (int i = 0; i < N; i++)

      if (a[i] > z)

          k += a[i];

      else

          k -= a[i];

  cout << k << endl;

  int x, y;

  cin >> x >> y;

  s = 0;

  while ((x != 0) && (x != 0))

  {

      x--;

      y--;

      s += x + y;

  }

  cout << s << endl;

  return;

}

  1.  После каждой строки программы проставить номер. Например, //1, //2 и т.д.
  2.  Выполнить трассировку программы  (без захода в функции стандартных библиотек), наблюдая за переменными в окне Locals.
  3.  Остановить отладку программы.
  4.  Установить точку остановки на операторе if (a[i] > z).
  5.  Выполнить программу до курсора на строке s = sum(a, N);
  6.  Продолжить выполнить программы до точки остановки. Далее продолжать пошаговое выполнение до строки cout << k << endl;.
  7.  Добавить в окно Watch 1 переменные x, y, s для наблюдения изменения их значений. Продолжать пошаговое выполнение.
  8.  Остановить отладку программы.
  9.  В операторе цикла while задать условную точку останова по числу проходов. Запустить программу для отладки.
  10.  Продолжать пошаговое выполнение до конца программы, наблюдая изменение значений x, y, s в окне Watch 1.
  11.  Записать полученные результаты.
  12.  Остановить отладку программы.
  13.  В операторе цикла while задать еще одну условную точку останова по логическому условию. Запустить программу для отладки
  14.  Продолжать пошаговое выполнение до конца программы, наблюдая изменение значений x, y, s в окне Watch 1.
  15.  Записать полученные результаты.

6 Содержание отчета

  1.  Титульный лист.
  2.  Наименование и цель работы.
  3.  Краткое теоретическое описание.
  4.  Задание на лабораторную работу.
  5.  Схема алгоритма.
  6.  Листинг программы.
  7.  Результаты выполнения программы.


 

А также другие работы, которые могут Вас заинтересовать

16493. Подмосковная усадьба Кусково 37 KB
  Тема: Подмосковная усадьба Кусково В круг памятников архитектуры нельзя не ввести ряд подмосковных усадеб некогда располагавшихся близко от границ столицы а ныне вошедших в ее территорию. Среди них имеются как очень большие типа дворцовых рези
16494. Искусство Среднего царства 76 KB
  Искусство Среднего царства На время VII–X династии приходится первый Период распада страны. По свидетельству Манефона 70 царей VII династии правили 70 дней. Эта образная характеристика воссоздает перед нами картину смут которые наступили после деце
16495. Римское искусство 21.5 KB
  Римское искусство. Искусство древнего Рима как и древней Греции развивалось в рамках рабовладельческого общества поэтому именно эти два основных компонента имеют ввиду когда говорят об античном искусстве. Искусство Рима считают завершением художественного твор...
16496. КУРС ЛЕКЦИЙ ПО ИСТОРИИ РОССИИ 460 KB
  КУРС ЛЕКЦИЙ ПО ИСТОРИИ РОССИИ ВЛАДИМИРА ДМИТРИЕВИЧА ЮДИНА. Главное содержание курса повествование о том как из разрозненных славянских племён образовалась Русь и единый русский народ как образовалась империя и как она распалась. Задача курса изложить последов
16497. Лекции по истории Русской Церкви 902 KB
  ВВЕДЕНИЕ. ПОНЯТИЕ О НАУКЕ ИСТОРИЯ РУССКОЙ ЦЕРКВИ ЕЁ ПРЕДМЕТ И ЗАДАЧА. ИСТОЧНИКИ. ИСТОРИОГРАФИЯ. ЛИТЕРАТУРА. ПЕРИОДИЗАЦИЯ. Древний философ Плутарх писал что история есть учитель жизни. Ключевский В.О. писал: Хотя и говорят о том что история никого и ничему не на
16498. КУРС ЛЕКЦИЙ ПО ИСТОРИИ РОССИИ 216 KB
  Г КУРС ЛЕКЦИЙ ПО ИСТОРИИ РОССИИ ВЛАДИМИРА ДМИТРИЕВИЧА ЮДИНА. лавное содержание курса повествование о том как из разрозненных славянских племён образовалась Русь и единый русский народ как образовалась империя и как она распалась. Задача курса изложить после
16499. П.А. Столыпин. Политический портрет 126.5 KB
  РЕФЕРАТ П.А. Столыпин политический портрет Содержание Глава первая. Политическая и экономическая ситуация в России в конце 19 начало 20 века. стр. 2 ...
16500. Римское право. Учебное пособие 1.27 MB
  Московский государственный университет имени М.В Ломоносова Центр общественных наук И. Б. Новицкий РИМСКОЕ ПРАВО Ассоциация Гуманитарное знание ТЕИС Москва 2002 ББК67 Ответственный редактор проф. Е.А. Суханов Рекомендовано Ученым советом юридич...
16501. Регрессные обязательства между социалистическими хозяйственными организациями. Учебное пособие 1.01 MB
  Термин «регресс» (противоположный «прогрессу» — «движению вперед») по буквальному значению выражает «движение назад, обратно». Поэтому, например, выражение «регрессное требование» нередко заменяют, в качестве синонима, термином «обратное требование». Однако не всякое обратное требование подойдет под категорию регрессного требования, как ее понимают закон и арбитражно-судебная практика