Как я могу получить трассировку стека с хвостовыми вызовами, включенными в Ocaml? - PullRequest
5 голосов
/ 03 сентября 2011

Стек вызовов в ocamldebug является реальным стеком вызовов, поэтому функции, которые сделали хвостовой вызов, не отображаются в нем. Это смущает. Как я могу получить обратную трассировку, которая включает хвостовые вызовы?

Ответы [ 2 ]

8 голосов
/ 03 сентября 2011

Самый простой способ - изменить свою функцию, чтобы она больше не была хвостовой рекурсивной. Это то, что я использую, когда я хочу, чтобы хорошие трассировки отображались, когда исключение прерывает программу (в этом случае ocamldebug не нужен, достаточно запустить программу под OCAMLRUNPARAM="b"; документация ).

Моя личная техника - изменить хвостовой вызов на

let result = <tail call> in result

Ocaml в основном компилирует код в том виде, в котором он написан, и в этом случае это здорово: компилятор этого не встроил, и вы получили красивый обратный след. Конечно, вы можете легко удалить эту деоптимизацию, как только ошибка найдена. (Это прекрасно работает, когда у вас есть только несколько оконечных вызовов; если у вас их много, вы можете заключить все тело функции в let result = <body> in result, но я нахожу это немного менее удобным и понятным.)

Если вам нужно, чтобы функция все еще была вызовом taill (например, у вас есть предел размера стека, установленный в ОС, который вы можете исчерпать), вы можете преобразовать стек вызовов для этой функции в структуру данных, превратив

let rec f arg1 arg2 .. argN =
  ...
  f arg1' arg2' .. argN'

в

let rec f stack arg1 arg2 .. argN =
 let stack' = (arg1,arg2,..,argN)::stack in
 ...
  f stack' arg1' arg2' .. argN'

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

0 голосов
/ 06 сентября 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...