Для примера рассмотрим такую программу:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>

#define N 10

int main()
{
    unsigned long seed;
    read(open("/dev/random", O_RDONLY), &seed, sizeof(seed));
    srand(seed);

    int a[N], i, s = 0;
    printf("My array:");
    for (i = 0; i < N; ++i)
    {
        a[i] = rand() % N;
        s += a[i];
        printf("%2d",  a[i]);
    }
    printf("\nSumm: %d\n", s);
    return 0;
}

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

Чтобы начать процесс отладки, сначала нужно поставить точку останова на какой-либо строке кода. Это можно сделать как минимум тремя способами:

  • кликнув по пустой области между номером нужной строки и вертикальной чертой, правее которой мы пишем код;
  • командой Toggle line breakpoint из меню Run;
  • нажав Ctrl+F8.

Точка останова на строке 14:

Точка останова на строке 14

Два последних способа корректно сработают при условии, что текстовый курсор находится на нужной строке кода. Можно также поставить временную точку останова (Ctrl+Alt+Shift+F8), она отличается от обычной тем, что пропадёт после первого срабатывания.

Если всё сделано верно, рядом с номером строки появится красный круг — маркер точки останова.

Теперь для начала процесса отладки нужно нажать кнопку с изображением зелёного жука в правой верхней части окна CLion (или Shift+F9).

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

В нижней части окна CLion будет открыта палитра Debug на вкладке Debugger. Палитра Debug:

Палитра Debug

В палитре есть вертикальный ряд кнопок слева, содержащий кнопки управления запуском программы, точками останова и две служебные кнопки — кнопку восстановления палитры Debug к виду по умолчанию, а также кнопку настроек. Горизонтальный ряд кнопок сверху содержит кнопки управления ходом и шагами отладки. На вкладке Debugger расположены окно Frames и две вкладки Variables и GDB, отделённые от окна Frames вертикальным рядом кнопок управления просматриваемыми переменными (далее, для краткости будем называть просмотриваемую переменную watch).

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

На вкладке Variables доступен список переменных, видимых в данный момент выполнения кода. В примере, т.к. 14 строка ещё не выполнена, мы пока можем видеть только переменную seed и её значение.

Тем не менее, всегда можно добавить на вкладку Variables и собственные выражения (кнопка + или клавиша Insert), и, если значение выражения может быть вычислено на текущий момент — увидеть значение. Для примера добавим три watch: N, i == N и k. Получим значения только первых двух выражений, т.к. отладчик “не знает” что такое k — такая переменная нигде не объявлена:

Локальные переменныые и пользовательские watch

Чтобы сделать шаг по коду (т.е. выполнить одну строку), нужно нажать клавишу F8 или выполнить команду Step Over из меню Run, либо нажать соответствующую кнопку на палитре Debug. Рекомендую изучить остальные варианты шагов по коду, их значение и способы применения.

Теперь в нашем примере выделена синим строка 15, соответственно, строка 14 уже выполнена и на вкладке Variables мы видим значения новых переменных. Как видно, массив a заполнен произвольными значениями, т.к. объявлен локально:

Значения локального массива a

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

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

Условная точка останова

Кроме того, в этом окне можно включить или выключить точку останова (Enabled), указать будет ли программа остановлена при достижении точки или нет (Suspend execution), и настроить другие параметры. По ссылке More откроется окно Breakpoints (его можно вызвать сочетанием Ctrl+Shift+8, либо нажатием кнопки с двумя красными кружками на палитре Debug, либо соответсвующим пунктом меню Run), в котором присутвуют все инструменты по управлению точками останова, рекомендую их изучить.

Для примера поставим точку останова на 19 строке, в поле Condition введём i == 7 и запустим отладку. Программа будет остановлена при выполнении этого условия.

На этом всё. Обязательно попробуйте отладить реальную программу на практике, используя полученные навыки.