dbg: трассировщик, визуализирующий рекурсивные функции, например отступом - PullRequest
4 голосов
/ 26 февраля 2011

У меня проблема с отладкой сложной рекурсивной функции, которую я использую идиомой:

dbg:tracer(),dbg:p(all,c),dbg:tpl(Mod,Fun1,x),dbg:tpl(Mod,Fun2,x)...

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

Есть ли простой способ сделать это более читабельным, например, с помощью отступа.

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

Ответы [ 2 ]

5 голосов
/ 26 февраля 2011

Тем временем я понял, как это сделать, на самом деле это не так уж сложно. Чтобы иметь процесс, обрабатывающий вывод сообщения трассировки, вам просто нужно использовать dbg:trace/2,3 и написать одну функцию, которая выполняет форматирование.

Мы пишем небольшой модуль, содержащий функцию для передачи на dbg:trace:

-module(trtool).
-export([nested/2]).

nested({trace, _Pid, call, {Mod, Fun, Param}}, Level) ->
    io:format("~s~p:~p ~p\n", 
              [lists:duplicate(Level, "|   "), Mod, Fun, Param]),
    Level + 1;
nested({trace, _Pid, return_from, {Mod, Fun, Arity}, Rval}, Level) ->
    L = Level - 1,
    io:format("~s~p:~p/~b -> ~p\n", 
              [lists:duplicate(L, "|   "), Mod, Fun, Arity, Rval]),
    L;
nested(Any, Level) ->
    io:format("trace_msg: ~p\n", [Any]),
    Level.

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

Второй формат - это состояние, которое может содержать любые данные. Мы передаем начальное значение при вызове dbg:trace и возвращаем следующее значение из нашей функции.

В примере nested мы просто пропускаем уровень отступа, который будет увеличиваться и уменьшаться в предложениях call и return_from.

Теперь давайте попробуем это, сначала вызвав dbg:tracer/2, первый параметр должен быть атомом process, второй параметр - кортеж, содержащий наше вновь написанное веселье и начальное значение для параметра состояния.

1> dbg:tracer(process, {fun trtool:nested/2, 0}).                         
{ok,<0.70.0>}

Затем мы настраиваем трассировку, как и раньше:

2> dbg:p(all, c), dbg:tpl(user_default,hop,x),dbg:tpl(user_default,rec,x).
{ok,[{matched,nonode@nohost,2},{saved,x}]}

Затем мы запускаем наш вызов функции для трассировки, и за вложением можно легко следовать:

3> rec(3).                                                                
user_default:rec [3]
|   user_default:rec [3,1,3]
|   |   user_default:rec [3,1,2]
|   |   |   user_default:rec [3,1,1]
|   |   |   |   user_default:rec [3,1,0]
|   |   |   |   |   user_default:hop [3,1,0]
|   |   |   |   |   user_default:hop/3 -> {3,21}
|   |   |   |   user_default:rec/3 -> {3,21,1}
|   |   |   |   user_default:rec [6,2,-1]
|   |   |   |   |   user_default:hop [6,2,1]
|   |   |   |   |   user_default:hop/3 -> {2,46}
|   |   |   |   user_default:rec/3 -> {2,46,1}
|   |   |   user_default:rec/3 -> {5,67,2}
|   |   |   user_default:rec [8,3,0]
|   |   |   |   user_default:hop [8,3,0]
|   |   |   |   user_default:hop/3 -> {3,144}
|   |   |   user_default:rec/3 -> {3,144,1}
|   |   user_default:rec/3 -> {8,211,3}
|   |   user_default:rec [11,4,1]
|   |   |   user_default:rec [11,4,0]
|   |   |   |   user_default:hop [11,4,0]
|   |   |   |   user_default:hop/3 -> {3,258}
|   |   |   user_default:rec/3 -> {3,258,1}
|   |   |   user_default:rec [14,5,-1]
|   |   |   |   user_default:hop [14,5,1]
|   |   |   |   user_default:hop/3 -> {2,260}
|   |   |   user_default:rec/3 -> {2,260,1}
|   |   user_default:rec/3 -> {5,518,2}
|   user_default:rec/3 -> {13,729,5}
user_default:rec/1 -> {15,729}
{15,729}
4>
2 голосов
/ 26 февраля 2011

Нет способа, которым вы можете сделать это с текущим процессом трассировки dbg, вы должны написать свой собственный. Если вы запустите dbg: tracer / 2 и используете процесс или порт для сбора данных и их распечатки так, как вы хотите.

Вероятно, это быстрее и проще, хотя (как вы говорите) анализировать данные после трассировки и затем форматировать их.

...