Spec-Zone.ru › OCaml 4.14

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

  • 18.1 Компиляция для отладки
  • 18.2 Вызов
  • 18.3 Команды
  • 18.4 Выполнение программы
  • 18.5 Точки останова
  • 18.6 Стек вызовов
  • 18.7 Просмотр значений переменных
  • 18.8 Управление отладчиком
  • 18.9 Разные команды
  • 18.10 Запуск отладчика в Emacs

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

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

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

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

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

18.2 Вызов

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

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

        ocamldebug [options] program [arguments]

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

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

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

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

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

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

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

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

18.3 Команды

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

        run
        goto 1000
        set arguments arg1 arg2

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

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

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

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

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

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

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

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

18.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
    

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Точка останова заставляет программу остановиться всякий раз, когда достигается определенная точка в программе. Ее можно установить несколькими способами, используя команду break. Точкам останова присваиваются номера при установке, для дальнейшей ссылки. Наиболее удобным способом установки точек останова является использование интерфейса Emacs (см. раздел 18.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
Вывести список всех точек останова.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

18.8.6 Поведение отладчика относительно fork

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Кроме того, 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/4.14/htmlman/debugger.html

Spec-Zone.ru

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