Spec-Zone.ru › OCaml
☰Инструменты OCaml
  • Партиционная компиляция (ocamlc)
  • Система интерпретатора или REPL (ocaml)
  • Система выполнения (ocamlrun)
  • Компиляция нативный код (ocamlopt)
  • Генераторы лексических и синтаксических анализаторов (ocamllex, ocamlyacc)
  • Генератор зависимостей (ocamldep)
  • Генератор документации (ocamldoc)
  • Отладчик (ocamldebug)
  • Профилирование (ocamlprof)
  • Интерфейс C с OCaml
  • Оптимизация с Flambda
  • Мультирование с afl-fuzz
  • Отслеживание выполнения с событиями среды выполнения
  • Программа преобразования «Хвостовой модуль конструктора»
  • Обнаружение гонок данных в среде выполнения с ThreadSanitizer

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

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

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

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

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

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

2 Вызов

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
Отобразить краткое резюме использования и завершить работу.

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

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

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

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

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

3 Команды

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

        run
        goto 1000
        set arguments arg1 arg2

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

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

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

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

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

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

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

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

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
    

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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
Вывести список всех точек останова.

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

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

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

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

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

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

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

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

simple-expr ::= lowercase-ident
∣ { capitalized-ident . } lowercase-ident
∣ *
∣ $ integer
∣ simple-expr . lowercase-ident
∣ simple-expr .( integer )
∣ simple-expr .[ integer ]
∣ ! simple-expr
∣ ( simple-expr )

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

8.4 Рабочий каталог

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

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

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

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

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

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

8.6 Поведение отладчика в отношении fork

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

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

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

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

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

8.8 Общение между отладчиком и программой

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

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

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

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

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

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

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

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

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

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

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
Удалить указанную функцию из таблицы принтеров значений.

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

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

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): отобразить значение идентификатора в точке
« Генератор документации (ocamldoc)Профилирование (ocamlprof) »
Copyright © 2024 Institut National de Recherche en Informatique et en Automatique

© 1995-2024 INRIA.
https://ocaml.org/manual/5.2/debugger.html

Spec-Zone.ru

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