dbg:tracer可视化递归函数,例如通过缩进 [英] dbg:tracer visualizing recursive functions e.g. by indenting

查看:142
本文介绍了dbg:tracer可视化递归函数,例如通过缩进的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有问题调试一个复杂的递归函数我使用的成语:

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

这给我一个对所有函数的调用的平面列表,很难找出哪个返回属于哪个调用。



<有没有一个简单的方法来使这更可读,例如通过缩进。



我可以稍后对每个通话的生成和缩进的文字进行处理,并且对于每个返回来说都是过往的,但这对我来说听起来不是很优雅。 >

解决方案

在此期间,我想出了如何做到这一点,其实并不太难。要处理跟踪消息输出的过程,您只需使用 dbg:trace / 2,3 并编写一个执行格式化的函数。



我们写一个包含该函数的小模块传递给 dbg:trace

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

嵌套({trace,_Pid,call,{Mod,Fun,Param}},Level) - >
io:format(〜s〜p:〜p〜p\\\

[lists:duplicate(Level,|),Mod,Fun,Param]),
级+ 1;
嵌套({trace,_Pid,return_from,{Mod,Fun,Arity},Rval},Level) - >
L =级别-1,
io:格式(〜s〜p:〜p /〜b - >〜p\\\

[ |),Mod,Fun,Arity,Rval]),
L;
嵌套(Any,Level) - >
io:format(trace_msg:〜p \\\
,[Any]),
级别。

该函数接受两个参数,首先它通过跟踪消息,这是一个方便的元组领域。要找出要格式化的消息的结构,只需从一个简单的函数开始,该函数打印例如函数的最后一个子句。



第二种格式是可以包含任何数据的状态。调用 dbg:trace 并从我们的函数返回下一个值时,我们传递初始值。



code>嵌套示例,我们只是传递将在调用 return_from中递增和递减的缩进级别子句



现在让我们试试一下,首先调用 dbg:tracer / 2 ,第一个参数必须是原子进程,第二个参数是一个包含我们新写的乐趣的元组和状态参数的初始值。

  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>


I have the problem debugging an complicated recursive function I'm using the idiom:

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

This gives me a flat list of calls to all functions where it is very hard to find out which return belongs to which call.

Is there a easy way to make this more readable e.g. by indenting.

I could just post process the text produced and indent for each call, and outdent for each return, but this sounds not very elegant to me.

解决方案

In the meantime I figured it out how to do this, its actually not too hard. To have a process handling the trace message output you just have to use dbg:trace/2,3 and write one function that does the formatting.

We write a small module containing the function to pass to 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.

The function takes two arguments, in the first it gets passed the trace message which is a tuple with convenient fields. To find out how the messages you want to format are structured just start with a simple function that prints everything like the last clause of the example function.

The second format is a kind of state that could contain any data. We pass the initial value when calling dbg:trace and return the next value from our function.

In the nested example we just pass the indent level which will be incremented and decremented in the call and return_from clauses.

Now lets try this out, first calling dbg:tracer/2, first parameter must be the atom process, second parameter a tuple containing our newly written fun and the initial value for the state param.

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

Then we set up tracing as before:

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

Then we start our function call to trace and the nesting can be easily followed:

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>

这篇关于dbg:tracer可视化递归函数,例如通过缩进的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆