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

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

В этой главе описывается отладчик OCaml для пошагового выполнения исходного кода с возможностью воспроизведения ocamldebug.

Отладчик доступен в системах, поддерживающих BSD-сокеты, включая Windows. В нативных версиях для Windows функции replay недоступны.

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

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

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

2 Запуск

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

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

        ocamldebug [options] program [arguments]

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

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

-c count
Установить максимальное число одновременно существующих контрольных точек равным count.
-cd dir
Запустить программу отладчика из рабочего каталога dir, а не из текущего каталога. (См. также команду cd.)
-emacs
Сообщить отладчику, что он запущен в Emacs. (Сведения о запуске отладчика в Emacs см. в разделе 20.10.)
-I directory
Добавить directory в список каталогов, в которых выполняется поиск исходных и скомпилированных файлов. (См. также команду directory.)
-s socket
Использовать socket для связи с отлаживаемой программой. Формат socket описан в разделе о команде set socket (раздел 20.8.8).
-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 переменные
Вывести значения указанных переменных. print можно сократить до p.
display переменные
То же, что и print, но глубина вывода ограничена значением 1. Полезно для просмотра больших структур данных без вывода их целиком. display можно сократить до d.

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

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

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 количество
Задать максимальное количество контрольных точек: количество. Большее количество контрольных точек позволяет вернуться дальше назад во времени, но требует больше памяти и создаёт больше процессов Unix.

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

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

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

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

8.10 Определяемые пользователем функции вывода

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

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

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

remove_printer имя функции вывода
Удалить указанную функцию из таблицы функций вывода значений.

9 Прочие команды

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

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

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

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

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

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

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)Нативная отладка (gdb, lldb) »
Авторские права © 2026 Национальный институт исследований в области информатики и автоматики

© 1995-2026 INRIA.
https://ocaml.org/manual/5.5/debugger.html

Spec-Zone.ru

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