Значение переменной j, равное 4, означает, что программа попыталась выполнить оператор
if (а[4].key > а[4+1].key)
У массива array, который вы передали функции sort, только пять элементов, которые пронумерованы от 0 до 4. Поэтому данный оператор считывает несуществующий элемент массива array[5]. Переменная цикла jприняла некорректное значение.
Если ваша программа завершилась в строке 25, система обнаружила чтение за пределами массива, только когда взялась за перестановку элементов массива, выполнив оператор
/* 25 */ а[j] = a[j+1];
который при j, равной 4, дает в результате
а[4] = а[4+1];
Просмотреть элементы передаваемого массива можно, применив выражение в команде print. В программе gdb вы можете использовать почти любое допустимое выражение языка С для вывода значения переменной, элемента массива или указателя.
(gdb) print а[3]
$2 = {data = "alex", '\0' , key = 1}
(gdb)
Отладчик gdb сохраняет результаты выполнения команд в псевдопеременных вида $< номер >. Результат последней команды всегда хранится в псевдопеременной $, а предыдущей — в $$. Это позволяет результат одной команды использовать в другой. Например:
(gdb) print j
$3 = 4
(gdb) print a[$-1].key
$4 = 1
Вы можете в программе gdb вывести на экран исходный текст программы с помощью команды list. Она выводит фрагмент кода, расположенного рядом с текущей позицией. Последующие вызовы listвыведут остальной текст. Команде listможно задать в качестве аргумента имя функции, и команда отобразит фрагмент текста в этом месте программы, или можно указать пару номеров строк, и на экране появится текст программы, находящийся между этими строками.
(gdb) list
18 /* 18 */ int s = 1;
19 /* 19 */
20 /* 20 */ for(; i < n && s != 0; i++) {
21 /* 21 */ s = 0;
22 /* 22 */ for(j = 0; j < n; j++) {
23 /* 23 */ if(a[j].key > a[j+1].key) {
24 /* 24 */ item t = a[j];
25 /* 25 */ a[j] = a[j+1];
26 /* 26 */ a[j+1] = t;
27 /* 27 */ s++;
(gdb)
В строке 22 задано выполнение цикла до тех пор, пока переменная jменьше n. В данном случае nравна 5, поэтому у jбудет последнее значение 4, слишком большое. Значение 4 приводит к сравнению а[4]с а[5]и возможной их перестановке. Единственное решение этой конкретной проблемы — исправить условие завершения цикла на следующее: j < n-1.
Давайте внесем это изменение, назовем новую программу debug4.c, откомпилируем ее и попробуем снова выполнить.
/* 22 */ for(j = 0; j < n-1; j++) {
$ cc -g -o debug4 debug4.с
$ ./debug4
array[0] = {john, 2}
array[1] = {alex, 1}
array[2] = {bill, 3}
array[3] = {neil, 4}
array[4] = {rick, 5}
Программа все еще не работает, поскольку она вывела неверно отсортированный список. Попробуем применить gdb для пошагового выполнения программы.
Для обнаружения места сбоя в программе необходимо иметь возможность проследить за тем, что делает программа во время выполнения. Остановить ее в любой момент можно с помощью точек останова. Они останавливают программу и передают управление отладчику. Вы сможете проверить переменные и затем разрешить программе продолжить выполнение.
В функции sortесть два цикла. Внешний цикл с переменной цикла iвыполняется для каждого элемента массива один раз. Внутренний или вложенный цикл меняет местами элемент с последующим, расположенным ниже в списке. Это создает эффект всплытия пузырьков, поднимая вверх меньшие элементы. После каждого выполнения внешнего цикла самый большой элемент опускается на дно. Вы можете убедиться в этом, остановив программу на внешнем цикле и просмотрев состояние массива.
Для установки точек останова применяется ряд команд. Их перечень получен отладчиком gdb с помощью команды help breakpoint:
(gdb) help breakpoint
Making program stop at certain points.
List of commands:
awatch -- Set a watchpoint for an expression
break -- Set breakpoint at specified line or function
catch -- Set catchpoints to catch events
clear -- Clear breakpoint at specified line or function
commands -- Set commands to be executed when a breakpoint is hit
condition -- Specify breakpoint number N to break only if COND is true
delete -- Delete some breakpoints or auto-display expressions
delete breakpoints -- Delete some breakpoints or auto-display expressions
delete checkpoint -- Delete a fork/checkpoint (experimental)
Читать дальше