Spec-Zone.ru › OCaml 5.0

Глава 20 Отладчик (ocamldebug)

  • 20.1 Компиляция для отладки
  • 20.2 Вызов
  • 20.3 Команды
  • 20.4 Выполнение программы
  • 20.5 Точки останова
  • 20.6 Стек вызовов
  • 20.7 Просмотр значений переменных
  • 20.8 Управление отладчиком
  • 20.9 Разные команды
  • 20.10 Запуск отладчика в Emacs

В этой главе описывается отладчик OCaml на уровне исходного кода ocamldebug.

Unix: Отладчик доступен на системах Unix, которые поддерживают сокеты BSD.
Windows: Отладчик доступен в порте Cygwin для OCaml, но не в родных портах Win32.

20.1 Компиляция для отладки

Перед использованием отладчика программа должна быть скомпилирована и связана с опцией -g: все файлы .cmo и .cma, которые являются частью программы, должны быть созданы с помощью ocamlc -g, и они должны быть связаны вместе с помощью ocamlc -g.

Компиляция с -g не влияет на время выполнения программ: объектные файлы и исполняемые файлы байт-кода больше и занимают больше времени для создания, но исполняемые файлы работают с точно такой же скоростью, как если бы они были скомпилированы без -g.

20.2 Вызов

20.2.1 Запуск отладчика

Отладчик OCaml вызывается путём запуска программы ocamldebug с именем исполняемого файла байт-кода в качестве первого аргумента:

        ocamldebug [options] program [arguments]

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

Признаются следующие параметры командной строки:

-c count
Устанавливает максимальное количество одновременно активных контрольных точек на count.
-cd dir
Запустить программу отладчика из рабочей директории dir вместо текущей директории. (См. также команду cd.)
-emacs
Сообщить отладчику, что он запущен в Emacs. (См. раздел 20.10 для получения информации о запуске отладчика в Emacs.)
-I directory
Добавить directory в список директорий, проверяемых на наличие исходных файлов и скомпилированных файлов. (См. также команду directory.)
-s socket
Использовать socket для связи с отлаживаемой программой. См. описание команды set socket (раздел 20.8.8) для формата socket.
-version
Вывести строку версии и завершить работу.
-vnum
Вывести короткий номер версии и завершить работу.
-help или --help
Вывести краткое описание использования и завершить работу.

20.2.2 Файл инициализации

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

20.2.3 Выход из отладчика

Команда quit завершает работу отладчика. Также можно выйти из отладчика, набрав символ конца файла (обычно ctrl-D).

Ввод символа прерывания (обычно ctrl-C) не выведет из отладчика, но прервёт выполнение любой команды отладчика, которая находится в процессе выполнения, и вернёт вас в командную строку отладчика.

20.3 Команды

Команда отладчика — это строка ввода. Она начинается с имени команды, за которым следуют аргументы, зависящие от этого имени. Примеры:

        run
        goto 1000
        set arguments arg1 arg2

Имя команды может быть укорочено, если нет неоднозначности. Например, go 1000 понимается как goto 1000, поскольку нет других команд, имена которых начинаются с go. Для наиболее часто используемых команд допускаются сокращения. Например, r означает run, даже если есть другие команды, начинающиеся с r. Вы можете проверить корректность сокращения, используя команду help.

Если предыдущая команда была успешной, пустая строка (только нажатие RET) повторит её.

20.3.1 Получение справки

В отладчике OCaml есть простая система справки, которая даёт краткое описание каждой команды и переменной.

help
Вывести список команд.
help command
Выдать справку по команде command.
help set variable, help show variable
Выдать справку по переменной variable. Список всех переменных отладчика можно получить с помощью help set.
help info topic
Выдать справку по topic. Используйте help info для получения списка известных тем.

20.3.2 Доступ к состоянию отладчика

set variable value
Установить переменную отладчика variable на значение value.
show variable
Вывести значение переменной отладчика variable.
info subject
Выдать информацию о заданном предмете. Например, info breakpoints выведет список всех точек останова.

20.4 Выполнение программы

20.4.1 События

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

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

Вот где расположены события отладчика (записанные ⋈) в исходном коде:

  • После применения функции:
    (f arg)⋈
    
  • При входе в функцию:
    fun x y z -> ⋈ ...
    
  • При каждом случае определения шаблона соответствия (функция, match…with конструкция, try…with конструкция):
    function pat1 -> ⋈ expr1
           | ...
           | patN -> ⋈ exprN
    
  • Между подвыражениями последовательности:
    expr1; ⋈ expr2; ⋈ ...; ⋈ exprN
    
  • В двух ветвях условного выражения:
    if cond then ⋈ expr1 else ⋈ expr2
    
  • В начале каждой итерации цикла:
    while cond do ⋈ body done
    for i = a to b do ⋈ body done
    

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

20.4.2 Запуск отлаживаемой программы

Отладчик начинает выполнять отлаживаемую программу только при необходимости. Это позволяет устанавливать точки останова или назначать переменные отладчика до начала выполнения. Существует несколько способов запуска выполнения:

run
Выполнить программу до достижения точки останова или завершения программы.
goto 0
Загрузить программу и остановить выполнение на первом событии.
goto time
Загрузить программу и выполнить её до указанного времени. Полезно, когда вы уже примерно знаете, в какое время возникает проблема. Также полезно для установки точек останова на значения функций, которые не были вычислены в момент времени 0 (см. раздел 20.5).

Выполнение программы зависит от информации, которую она получает при запуске отладчика, например, аргументы командной строки программы и её рабочий каталог. Отладчик предоставляет команды для задания этой информации (set arguments и cd). Эти команды должны быть использованы до начала выполнения программы. Если вы попытаетесь изменить аргументы или рабочий каталог после запуска программы, отладчик завершит программу (после запроса подтверждения).

20.4.3 Выполнение программы

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

run
Выполнить программу вперёд с текущего времени. Останавливается на следующей точке останова или при завершении программы.
reverse
Выполнить программу назад с текущего времени. В основном полезно для возврата к последней найденной точке останова до текущего времени.
step [count]
Выполнить программу и остановиться на следующем событии. С аргументом, сделать это count раз. Если count равно 0, выполнять до завершения программы или достижения точки останова.
backstep [count]
Выполнить программу назад и остановиться на предыдущем событии. С аргументом, сделать это count раз.
next [count]
Выполнить программу и остановиться на следующем событии, пропуская вызовы функций. С аргументом, сделать это count раз.
previous [count]
Выполнить программу назад и остановиться на предыдущем событии, пропуская вызовы функций. С аргументом, сделать это count раз.
finish
Выполнить программу до возврата из текущей функции.
start
Выполнить программу назад и остановиться на первом событии перед текущим вызовом функции.

20.4.4 Путешествие во времени

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

При перемещении по программе отладчик сохраняет историю последовательных моментов времени, в которых вы останавливаетесь. Команда last может использоваться для возвращения к этим моментам времени: каждая команда last перемещает историю на один шаг назад. Это полезно в основном для отмены команд, таких как step и next.

goto time
Перейти к заданному времени.
last [count]
Вернуться к последнему записанному времени в истории выполнения. С аргументом, сделать это count раз.
set history size
Установить размер истории выполнения.

20.4.5 Завершение программы

kill
Завершить выполняемую программу. Эта команда полезна, если вы хотите перекомпилировать программу, не выходя из отладчика.

20.5 Точки останова

Точка останова заставляет программу остановиться всякий раз, когда достигается определённая точка в программе. Она может быть установлена несколькими способами, используя команду break. Точкам останова присваиваются номера при установке для дальнейшей ссылки. Наиболее удобный способ установки точек останова - через интерфейс Emacs (см. раздел 20.10).

break
Установите точку останова в текущей позиции выполнения программы. Текущая позиция должна находиться на событии (т.е. не в начале и не в конце программы).
break function
Установите точку останова в начале функции function. Это работает только тогда, когда функциональное значение идентификатора function вычислено и присвоено идентификатору. Поэтому данная команда не может быть использована в самом начале выполнения программы, когда все идентификаторы ещё не определены; используйте goto time для продвижения выполнения до тех пор, пока функциональное значение не станет доступным.
break @ [module] line
Установите точку останова в модуле module (или в текущем модуле, если module не указан), на первом событии строки line.
break @ [module] line column
Установите точку останова в модуле module (или в текущем модуле, если module не указан), на событии, ближайшем к строке line, столбцу column.
break @ [module] # character
Установите точку останова в модуле module на событии, ближайшем к символу с номером character.
break frag:pc, break pc
Установите точку останова по кодовому адресу frag:pc. Целое число frag — это идентификатор фрагмента кода, набора модулей, загруженных одновременно, либо изначально, либо с модулем Dynlink. Целое число pc — счётчик команд внутри этого фрагмента кода. Если frag опущен, по умолчанию он равен 0, что соответствует фрагменту кода программы, загруженному изначально.
delete [breakpoint-numbers]
Удалить указанные точки останова. Без аргумента — удалить все точки останова (после запроса подтверждения).
info breakpoints
Вывести список всех точек останова.

20.6 Стек вызовов

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

В любой момент времени одна из записей стека “выделена” отладчиком; несколько команд отладчика неявно ссылаются на выделенную запись. В частности, всякий раз, когда вы запрашиваете отладчик значение локальной переменной, значение находится в выделенной записи. Команды frame, up и down выбирают ту запись, которая вас интересует.

Когда программа останавливается, отладчик автоматически выделяет текущую выполняемую запись и кратко описывает её, как это делает команда frame.

frame
Описать текущую выделенную запись стека.
frame frame-number
Выбрать запись стека по номеру и описать её. Запись, которая выполнялась в момент остановки программы, имеет номер 0; её вызывающая запись имеет номер 1 и так далее по стеку вызовов.
backtrace [count], bt [count]
Вывести стек вызовов. Это полезно, чтобы увидеть, какая последовательность вызовов функций привела к текущей выполняемой записи. С положительным аргументом выводится только count самых внутренних записей. С отрицательным аргументом выводится только -count самых внешних записей.
up [count]
Выбрать и отобразить запись стека, расположенную “выше” выделенной записи, то есть запись, которая вызвала выделенную запись. Аргумент определяет количество записей, на которые нужно подняться.
down [count]
Выбрать и отобразить запись стека, расположенную “ниже” выделенной записи, то есть запись, которая была вызвана выделенной записью. Аргумент определяет количество записей, на которые нужно опуститься.

20.7 Просмотр значений переменных

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

Выводимые выражения представляют собой подмножество выражений OCaml, как описано в следующей грамматике:

простое-выражение ::= нижнего-регистра-идентификатор
∣ { заглавной-буквы-идентификатор . } нижнего-регистра-идентификатор
∣ *
∣ $ целое-число
∣ простое-выражение . нижнего-регистра-идентификатор
∣ простое-выражение .( целое-число )
∣ простое-выражение .[ целое-число ]
∣ ! простое-выражение
∣ ( простое-выражение )

Первые два случая относятся к идентификатору значения, либо без квалификации, либо с путём к структуре, которая его определяет. * относится к результату, только что вычисленному (как правило, к значению вызова функции), и допустим только если выбранное событие является “после” событием (как правило, вызов функции). $ целое-число относится к ранее выведенному значению. Остальные четыре формы выбирают часть выражения: соответственно, поле записи, элемент массива, элемент строки и текущее содержимое ссылки.

print variables
Вывести значения заданных переменных. print может быть сокращено до p.
display variables
То же, что print, но ограничить глубину вывода до 1. Полезно для просмотра больших структур данных без их полного вывода. display может быть сокращено до d.

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

set print_depth d
Ограничить вывод значений максимальной глубиной d.
set print_length l
Ограничить вывод значений до максимум l узлов.

20.8 Управление отладчиком

20.8.1 Установка имени и аргументов программы

set program файл
Установить имя программы на файл.
set arguments аргументы
Указать аргументы как аргументы командной строки для программы.

Для передачи аргументов отлаживаемой программе используется оболочка. Поэтому вы можете использовать подстановки, переменные оболочки и перенаправления файлов внутри аргументов. Для отладки программ, которые читают со стандартного ввода, рекомендуется перенаправлять их ввод из файла (используя set arguments < input-file), в противном случае ввод программы и ввод отладчика не будут должным образом разделены, а ввод не будет должным образом воспроизведен при выполнении программы назад.

20.8.2 Загрузка программ

Переменная loadingmode управляет тем, как выполняется программа.

set loadingmode direct
Программа выполняется непосредственно отладчиком. Это режим по умолчанию.
set loadingmode runtime
Отладчик выполняет OCaml-интерпретатор ocamlrun на программе. Редко полезно; кроме того, это предотвращает отладку программ, скомпилированных в режиме «пользовательского времени выполнения».
set loadingmode manual
Пользователь вручную запускает программу, когда отладчик попросит. Позволяет удаленную отладку (см. раздел 20.8.8).

20.8.3 Путь поиска файлов

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

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

directory имена_каталогов
Добавить указанные каталоги в путь поиска. Эти каталоги добавляются в начало и поэтому будут проверяться в первую очередь.
directory имена_каталогов for имя_модуля
То же, что и directory имена_каталогов, но указанные каталоги будут проверяться только при поиске исходного файла модуля, который был упакован в имя_модуля.
directory
Сбросить путь поиска. Это требует подтверждения.

20.8.4 Рабочая директория

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

cd директория
Установить рабочую директорию для ocamldebug на директория.
pwd
Вывести рабочую директорию для ocamldebug.

20.8.5 Включение и выключение обратного выполнения

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

Обычно отладчик периодически создает контрольные точки состояния программы. То есть он создаёт копию текущего состояния программы (используя системный вызов Unix fork). Если переменная checkpoints установлена в off, отладчик не будет создавать контрольные точки.

set checkpoints on/off
Выбрать, создавать ли отладчику контрольные точки или нет.

20.8.6 Поведение отладчика по отношению к fork

Когда программа вызывает fork, отладчик может следовать за дочерним или родительским процессом. По умолчанию отладчик следует за родительским процессом. Переменная follow_fork_mode управляет этим поведением:

set follow_fork_mode child/parent
Выбрать, следовать ли за дочерним или родительским процессом в случае вызова fork.

20.8.7 Остановка выполнения при загрузке нового кода

Отладчик совместим с модулем Dynlink. Однако, когда внешний модуль ещё не загружен, невозможно установить точку останова в его коде. Для облегчения установки точек останова в динамически загруженном коде отладчик останавливает программу каждый раз, когда загружаются новые модули. Это поведение можно отключить с помощью переменной break_on_load:

set break_on_load on/off
Выбрать, останавливать ли после загрузки нового кода.

20.8.8 Связь между отладчиком и программой

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

set socket сокет
Использовать сокет для связи с программой. сокет может быть именем файла или указанием интернет-порта хост:порт, где хост — имя хоста или интернет-адрес в точечной нотации, а порт — номер порта на хосте.

Со стороны отлаживаемой программы имя сокета передаётся через переменную окружения CAML_DEBUG_SOCKET.

20.8.9 Тонкая настройка отладчика

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

END_OF_DOCUMENT_MARKER
set processcount count
Установите максимальное количество контрольных точек на count. Большее количество контрольных точек позволяет вернуться дальше во времени, но использует больше памяти и создает больше процессов Unix.

Поскольку создание контрольных точек довольно дорого, его не следует делать слишком часто. С другой стороны, обратное выполнение быстрее, когда контрольные точки создаются чаще. В частности, обратное пошаговое выполнение более отзывчиво, когда много контрольных точек было создано непосредственно перед текущим временем. Для настройки стратегии создания контрольных точек отладчик не создаёт контрольных точек с одинаковой частотой для больших перемещений (например, run) и малых (например, step). Две переменные bigstep и smallstep содержат количество событий между двумя контрольными точками в каждом случае.

set bigstep count
Установите количество событий между двумя контрольными точками для больших перемещений.
set smallstep count
Установите количество событий между двумя контрольными точками для малых перемещений.

Следующие команды отображают информацию о контрольных точках и событиях:

info checkpoints
Вывести список контрольных точек.
info events [module]
Вывести список событий в заданном модуле (по умолчанию — текущий модуль).

20.8.10 Пользовательские принтеры

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

load_printer "file-name"
Загрузить в отладчик указанный файл-объект .cmo или .cma. Файл загружается в среде, содержащей только стандартную библиотеку OCaml плюс определения, предоставленные файлами-объектами, ранее загруженными с помощью load_printer. Если этот файл зависит от других файлов-объектов, ещё не загруженных, отладчик автоматически загрузит их, если сможет найти их в пути поиска. Загруженный файл не имеет прямого доступа к модулям отлаживаемой программы.
install_printer printer-name
Зарегистрировать функцию с именем printer-name (путь к значению) в качестве принтера для объектов, типы которых соответствуют типу аргумента функции. То есть, отладчик будет вызывать printer-name, когда у него есть такой объект для вывода. Функция вывода printer-name должна использовать модуль библиотеки Format для получения своего вывода, в противном случае его вывод не будет правильно расположен в выводимых значениях цикла верхнего уровня.

Путь к значению printer-name должен ссылаться на одну из функций, определённых в файлах-объектах, загруженных с помощью load_printer. Он не может ссылаться на функции отлаживаемой программы.

remove_printer printer-name
Удалить указанную функцию из таблицы принтеров значений.

20.9 Разные команды

list [module] [beginning] [end]
Вывести исходный код модуля module с номера строки beginning по номер строки end. По умолчанию отображается 20 строк текущего модуля, начиная с 10 строк перед текущей позицией.
source filename
Прочитать команды отладчика из скрипта filename.

20.10 Запуск отладчика под Emacs

Самый удобный способ использования отладчика — запуск его под Emacs с режимом OCaml, доступным через MELPA, а также по адресу https://github.com/ocaml/caml-mode.

Отладчик OCaml запускается под Emacs командой M-x camldebug с аргументом именем исполняемого файла progname для отладки. Связь с отладчиком происходит в буфере Emacs с именем *camldebug-progname*. Для взаимодействия с отладчиком доступны возможности редактирования и истории режима Shell.

Кроме того, Emacs отображает исходные файлы, содержащие текущее событие (текущая позиция в выполнении программы), и выделяет местоположение события. Эта информация обновляется синхронно с действием отладчика.

В буфере *camldebug-progname* доступны следующие сочетания клавиш для наиболее распространённых команд отладчика:

C-c C-s
(команда step): выполнить программу на один шаг вперёд.
C-c C-k
(команда backstep): выполнить программу на один шаг назад.
C-c C-n
(команда next): выполнить программу на один шаг вперёд, пропустив вызовы функций.
Средняя кнопка мыши
(команда display): отображение именованного значения. $n под курсором мыши (поддержка инкрементного просмотра больших структур данных).
C-c C-p
(команда print): вывести значение идентификатора в текущей позиции.
C-c C-d
(команда display): вывести значение идентификатора в текущей позиции.
C-c C-r
(команда run): выполнить программу вперёд до следующей точки останова.
C-c C-v
(команда reverse): выполнить программу назад до последней точки останова.
C-c C-l
(команда last): вернуться на один шаг назад в истории команд.
C-c C-t
(команда backtrace): вывести трассировку стека вызовов функций.
C-c C-f
(команда finish): выполнить вперёд до возврата текущей функции.
C-c <
(команда up): выбрать кадр стека ниже текущего.
C-c >
(команда down): выбрать кадр стека выше текущего.

Во всех буферах в режиме редактирования OCaml также доступны следующие команды отладчика:

C-x C-a C-b
(команда break): установить точку останова в ближайшем к точке событии
C-x C-a C-p
(команда print): вывести значение идентификатора в точке
C-x C-a C-d
(команда display): отобразить значение идентификатора в точке

© 1995-2022 INRIA.
https://v2.ocaml.org/releases/5.0/htmlman/debugger.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API