Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
31
Добавлен:
16.04.2013
Размер:
189.91 Кб
Скачать

4. Методика отладки программы

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

Для разработки тестов используются различные методы. Воспользуемся одним из них - методом анализа граничных значений. Согласно этому методу для построения тестов применяются следующие общие правила:

1) построить тесты для границ области значений входных дан­ных и тесты с неправильными входными данными для ситуаций незна­чительного выхода за границы области. Например, если входная строка может содержать от 1 до 80 символов, то нужно написать тесты для 0, 1, 80 и 81 символа;

2) построить тесты для получения (вычисления) минимального и максимального результирующих значений, а также построить (если это возможно) тесты, вызывающие получение результатов, которые меньше минимально допустимых значений и больше максимально до­пустимых значений. Например, если программа подсчитывает коли­чество пробелов во входной строке, содержащей не более 80 симво­лов, то нужно написать тесты, для которых программа должна выдать в качестве результата числа 0, 1, 80;

3) если входные данные или результаты являются последова­тельностью значений, то построить тесты для проверки первого, среднего и последнего значений в этой последовательности. Напри­мер, если программа отыскивает самое длинное слово в строке, то нужно использовать тесты в виде строк, в которых самое длинное слово находится в начале, середине и конце строки;

4) если входные данные или результаты являются последова­тельностью с переменным количеством значений, то построить тесты для случаев, когда эта последовательность оказывается (а) пустой и (б) содержит максимально возможное количество значений. Напри­мер, если программа отображает на экране n-буквенные слова, со­держащиеся в строке, то нужно написать тесты в виде (а) строки, в которой нет ни одного n-буквенного слова, и (б) строки, состоящей только из n-буквенных слов.

Отладим программу, которая должна суммировать определенное количество элементов массива, состоящего из 10 целых чисел, начи­ная с элемента с заданным номером (рис.1).

{ 1} Program SUM; {$R+ Включить контроль диапазона значений}

{ 2} Const

{ 3} SIZE = 10; { Количество элементов в массиве}

{ 4} Type NUMBER = 0..SIZE;{ Тип номеров и числа элементов }

{ 5} MAS = array [1..SIZE] of smallint;

{ 6} Var

{ 7} Arr : MAS; { Исходный массив }

{ 8} f, { Номер начального элемента в сумме }

{ 9} n : NUMBER; { Число элементов в сумме }

{10} Procedure getarr {--- Ввод массива }

{11} (M : MAS); { Вводимый массив }

{12} Var

{13} i : smallint; { Параметр цикла }

{14} begin { getarr }

{15} for i:=1 to SIZE do

{16} begin

{17} write('Введите ',i,'-й элемент: ');

{18} readln(M[i]);

{19} end;

{20} end; { getarr }

{21} Procedure putarr {--- Вывод массива}

{22} (M : MAS; { Выводимый массив}

{23} name : string); { Имя массива }

{24} Var

{25} i : smallint; { Параметр цикла }

{26} begin { putarr }

{27} for i:=1 to SIZE do

{28} write(name,i:1,'=',M[i],' ');

{29} writeln;

{30} end; { putarr }

{31} Function getsum {--- Вычисление суммы элементов }

{32} (M : MAS; { Исходный массив }

{33} n1, {Номер начального элемента в сумме}

{34} k : NUMBER { Число элементов в сумме}

{35} ) : smallint;

{36} Var

{37} i : smallint; { Параметр цикла }

{38} sum1 : smallint; { Сумма элементов }

{39} begin { getsum }

{40} for i:=1 to k do

{41} sum1 := sum1 + M[n1+i];

{42} end; { getsum }

{43} Begin { SUM }

{44} getarr(Arr);

{45} repeat

{46} putarr(Arr,'Arr');

{47} write('Hомеp начального элемента(0-выход): ');

{48} readln(f);

{49} if f>0 then

{50} begin

{51} write('Количество элементов: ');

{52} readln(n);

{53} if f+n<SIZE then

{54} writeln('Cумма элементов: ',getsum(Arr,f,n))

{55} else

{56} writeln('Выход за границы массива');

{57} write('Нажмите Enter'); readln;

{58} end;

{59} until f = 0;

{60} End. { SUM }

Рис.1. Отлаживаемая программа

Входными данными для программы служат 10 целых чисел (эле­менты массива), номер элемента, с которого начинается суммирова­ние, и количество суммируемых элементов. Результатом выполнения программы является вычисленная сумма заданного количества элемен­тов массива.

Для тестирования программы воспользуемся наборами данных, приведенными в табл.4. Прочерк в графе "Ожидаемый результат" означает семантическую ошибку, сопровождаемую сообщением "Range check error" (недопустимое значение переменной).

Таблица 4

Тесты для проверки программы SUM

Номер

Теста

Входные данные

Ожидае-

мый ре-

зультат

Номера правил для анализа граничных значений

Arr

f

n

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

1,1,1,1,1,1,1,1,1,1

1,1,1,1,1,1,1,1,1,1

1,1,1,1,1,1,1,1,1,1

1,1,1,1,1,1,1,1,1,1

1,1,1,1,1,1,1,1,1,1

1,0,0,0,0,0,0,0,0,0

1,0,0,0,0,0,0,0,0,0

1,1,1,1,1,1,1,1,1,1

1,1,1,1,1,1,1,1,1,1

1,1,1,1,1,1,1,1,1,1

-20000,0,0,0,0,0,0,0,

0,-12768

20000,0,0,0,0,0,0,0,

0, 12767

-20000,0,0,0,0,0,0,0,

0,-12769

20000,0,0,0,0,0,0,0,

0, 12768

0,0,0,0,0,1,0,0,0,0

1,1,1,1,1,1,1,1,1,1

1

1

10

11

10

1

1

10

10

-1

1

1

1

1

6

0

10

11

1

1

2

1

0

0

-1

1

10

10

10

10

1

-

10

-

1

-

Выход за

границы

массива

1

0

0

-

-

-32768

32767

-32769

32768

1

Выход из

програм-

мы SUM

1

1

1,3

1

1

1,3

1,3

1,3

1

1

2

2

2

2

3

1

Отладку программы осуществим по следующему протоколу.

1. Загрузить программу из файла SUM.DPR в окно редактора и запустить ее на выполнение.

2. Ввести входные данные, соответствующие тесту 1 (см. табл.4). Обратить внимание, что значения элементов массива, выво­димые процедурой putarr для контроля, отличаются от значений, введенных процедурой getarr.

3. Проанализировать ситуацию. Обнаруженное различие значений обусловлено ошибкой в процедуре ввода getarr или в процедуре вы­вода putarr.

4. Проверить процедуру ввода. Для этого:

а) поместить в окно отладки Watch List имя массива Arr, указав имя массива в тексте программы и нажав клавиши Ctrl-F5;

б) добавить в окно отладки имя массива М (формального пара­метра в процедуре getarr), нажав клавишу INS (Insert) и набрав имя массива с последующим нажатием Enter;

в) находясь в окне отладки (Ctrl-Alt-W), выполнить трассировку процедуры getarr, нажимая клавишу F7 и вводя значения элементов массива, соответствующие тесту 1;

г) перед выходом из процедуры getarr и после выхода из нее убедиться, что массив Arr не содержит значений, введенных в массив М.

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

6. Исправить ошибку. Перейти в окно редактора, содержащее текст программы SUM. Вставить зарезервированное слово VAR перед именем параметра М в заголовке процедуры getarr.

Отменить режим трассировки, нажав клавиши Ctrl-F2.

7. Проверить исправленную процедуру ввода. Для этого перейти в окно отладки Watch List и выполнить трассировку процедуры getarr, как указано в пункте 4в. Убедиться, что после выхода из процедуры getarr массив Arr содержит введенные значения элементов.

8. Продолжить выполнение программы, нажав клавиши F9.

Убедиться, что для теста 1 программа вместо вычисления суммы вы­водит сообщение "Выход за границы массива".

9. Проанализировать ситуацию. Появившееся на экране сообщение выводится из-за того, что не удовлетворяется условие f+n<SIZE в условном операторе, записанном в строке 53 (см. рис.1). Поскольку входные данные являются допустимыми, то ошибка содер­жится в проверяемом условии f+n<SIZE. Из анализа граничных значе­ний переменных f и n следует, что правильным будет условие f+n-1<=SIZE.

10. Исправить ошибку. Поместить курсор в строку 53 программы и набрать правильное условие f+n-1<=SIZE.

11. Повторить выполнение программы для теста 1. Убедиться, что вместо ожидаемого результата возникает семантическая ошибка, сопровождаемая сообщением "Range check error".

12. Проанализировать ситуацию. Место ошибки указано курсором: это оператор присваивания в функции getsum (строка 41).

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

13. Проверить функцию getsum. Установить курсор в строку 54. Выполнить программу для теста 1 до этой строки, нажав кла­вишу F4. Перейти в окно отладки Watch List и добавить в него имена глобальных переменных f, n, и локальных переменных n1, k, i, sum1, используемых в функции (см. пункт 4б). Выполнить трассиров­ку функции getsum, нажимая клавишу F7 и наблюдая за значениями переменных в окне отладки до тех пор, пока не появится сообщение об ошибке.

14. Проанализировать ситуацию. В разделе операторов функции

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

sum1 := 0;

перед циклом.

Наблюдение за значениями переменных во время трассировки цикла показывает, что сложение элементов массива выполняется пра­вильно до тех пор, пока не доходит очередь до последнего элемента (i=10): при попытке выполнить оператор присваивания

sum1 := sum1 + M[n1+i]

возникает семантическая ошибка, сопровождаемая сообщением "Range

check error". Эта ошибка связана с тем, что неправильно задан ин­декс элемента (при n1=1 и i=10 индекс n1+i равен 11). Правильным является индекс n1+i-1.

15. Исправить ошибки. В окне редактора набрать оператор sum1 := 0;

перед циклом в функции getsum и исправить индекс на n1+i-1.

16. Проверить исправленную функцию. Для этого установить

курсор в строку 42, в которой заканчивается описание функции

getsum, и выполнить программу для теста 1 до этой строки, нажав

клавишу F4. Перейти в окно отладки и убедиться, что сумма вы­числена правильно.

17. Продолжить выполнение программы, нажав клавиши F9.

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

18. Проанализировать ситуацию. Поскольку проверено, что

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

getsum := sum1

необходимый для передачи вычисленной суммы элементов массива.

19. Исправить ошибку. Перейти в окно редактора и в конце

описания функции getsum перед словом end набрать оператор

getsum := sum1

20. Проверить исправленную функцию. Для этого выполнить про­грамму для теста 1, нажав клавиши F9. Убедиться, что получен ожидаемый результат.

21. Продолжить тестирование программы. Ввести входные дан-

ные, соответствующие тестам 2-12 (см. табл.4), и убедиться, что

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

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

программы с входными данными, сумма которых оказывается меньше

минимально возможного числа типа smallint. Убедиться, что для

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

22. Проанализировать ситуацию. Неправильный результат для

теста 13 обусловлен особенностью выполнения арифметических опера­ций над величинами целого типа (в данном случае над величинами типа smallint): тип результата совпадает с типом операн­дов, причем возможное переполнение результата никак не контроли­руется; если операнды относятся к различным целым типам, то тип результата совпадает с типом того операнда, который имеет макси­мальный диапазон значений.

Можно проверить, как суммируются элементы массива для теста 13 в функции getsum. Для этого установим условную точку прерыва­ния в строке 41 (см. рис.1) и посмотрим, что происходит при сложении 10-го элемента массива:

а) поместить курсор в строку 41 и установить в этой строке точку прерывания, нажав клавиши F5; в результате строка 41 выделяется красным цветом;

б) вывести список точек прерывания, выбрав команду View Debug Windows| Breakpoints;

в) вызвать окно редактирования точки прерывания, нажав кла­виши Ctrl-E;

г) в третьей строке окна набрать условие прерывания i=10, при котором выполнение программы приостановится, и нажать Enter, а затем Esc.

д) выполнить программу для теста 13, нажав клавиши F9; после сложения девяти элементов массива в getsum, когда удовлет­ворится условие прерывания i=10, выполнение программы приостано­виться в строке 41 перед оператором присваивания;

е) перейти в окно отладки Watch List и убе­диться в правильности значения переменной sum1, равном -20000;

ж) нажать клавишу F7, чтобы прибавить 10-й элемент массива, равный -12769, и убедиться, что переменная sum1 принимает непра­вильное значение;

з) отменить режим отладки, нажав клавиши Ctrl-F2, и удалить точку прерывания, поместив курсор в строку 41 и нажав F5.

Итак, если не изменять тип результата, вычисляемого функцией getsum, то для некоторых сочетаний элементов массива Arr сумма будет вычисляться неправильно. Поэтому следует заменить тип ре­зультата smallint типом longint, чтобы правильность суммы не за­висила от допустимых значений элементов массива (-32768..+32767).

23. Исправить ошибку. В строках 35 и 38 заменить тип ре­зультата функции и переменной sum1 типом longint.

24. Проверить исправленную функцию. Для этого, нажав клавиши Ctrl-F9, выполнить программу для двух тестов, в которых суммиру­ются (1) 10 элементов, равных -32768, и (2) 10 элементов, равных

32767. Убедиться в правильности полученных результатов.

25. Продолжить тестирование программы. Ввести входные данные, соответствующие тестам 13-16 (см. табл.4), и убедиться, что результаты выполнения программы совпадают с ожидаемыми.

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

Соседние файлы в папке ВМИП