2011-06-22 112 views
27

我有一些Ruby和Java背景,我习惯于在错误日志中有确切的行数。如何调试Erlang代码?

所以,如果在编译的代码中有错误,我会看到在控制台输出中导致异常的行数。

如在此红宝石例如:

my_ruby_code.rb:13:in `/': divided by 0 (ZeroDivisionError) 
    from my_ruby_code.rb:13 

它的简单和快速的 - 我只是去行号13和修复错误。

相反,二郎只是说是这样的:

** exception error: no match of right hand side value [xxxx] 
in function my_module:my_fun/1 
in call from my_module:other_fun/2 

没有行号去看看。

如果我有两行一样

X = Param1, 
Y = Param2, 
在“my_fun”

,如何理解其中一线问题所在?另外,我试图从Vim切换到Emacs + Elang模式,但目前为止唯一的奖励是能够在Emacs(C-k`)内循环编译错误。

因此,编写代码和寻求简单的逻辑错误(如“不匹配右侧”)的过程似乎有点麻烦。

我试图在代码中添加很多“io:format”行,但这是需要时间的额外工作。

我也尝试过使用distel,但它需要10个步骤才能打开调试器一次。

问题:

  1. 什么是调试二郎代码的最直接和简单的方式?
  2. 相比Vim,Emacs的erlang模式在Erlang开发方面有什么优越之处吗?
  3. 你更喜欢什么开发'写 - 编译 - 调试'循环?您是否让Emacs编译并在终端中运行代码?你如何在你的Erlang代码中搜索错误?
+0

请选择哪个答案解决您的问题,如果有的话。 –

回答

17

您可以使用Erlang debugger单步执行代码并查看哪条线路发生故障。

erl,开始调试:

debugger:start(). 

然后你可以选择你想在解释模式下使用UI或使用控制台(调试)可以非常II哪些模块:

ii(my_module). 

添加断点在UI或控制台进行再次:

ib(my_module, my_func, func_arity). 

另外,在Erlang R15中,我们最终会在堆栈轨迹中有行号!

+0

但我仍然猜测Erlang调试器正在开发中......它是否稳定? – niting112

+1

调试器上仍有工作正在进行,但我发现它足够稳定,可以使用。在使用RabbitMQ或相关插件时,我已经使用了相当多的代码来调试问题 - 这是一个非常庞大的Erlang代码库。 –

+0

@ niting112 Erlang调试器是一款经过生产测试的工具,性能可靠。它是发行版的标准测试部分。当wx版本发布时,出现了一些稳定性回归,但那些已经得到解决。 –

33

调试Erlang代码有时可能会非常棘手,尤其是处理badmatch错误。在一般情况下,两个很好的指导方针,以保持有:

  • 保持功能,短期直接
  • 使用返回值如果可以的话,而不是绑定临时变量(这会给你越来越function_clause错误等,这是方式的好处更多的信息)

这就是说,使用调试器通常需要快速到达错误的底部。我建议使用命令行调试器dbg而不是图形的debugger(当你知道如何使用它时,它的速度会更快,而且你不必从Erlang shell切换到GUI)。

给你提供的样品表达,情况往往是,你拥有的不仅仅是变量更被分配到其他变量(这是在二郎山完全没有必要):

run(X, Y) -> 
    X = something(whatever), 
    Y = other:do(more_data), 

调试这里badmatch错误辅助通过使用命令行调试:

1> dbg:tracer().       % Start the CLI debugger 
{ok,<0.55.0>} 
2> dbg:p(all, c).       % Trace all processes, only calls 
{ok,[{matched,[email protected],29}]} 
3> dbg:tpl(my_module, something, x).  % tpl = trace local functions as well 
{ok,[{matched,[email protected],1},{saved,x}]} 
4> dbg:tp(other, do, x).     % tp = trace exported functions 
{ok,[{matched,[email protected],1},{saved,x}]} 
5> dbg:tp(my_module, run, x).    % x means print exceptions 
{ok,[{matched,[email protected],1},{saved,x}]} % (and normal return values) 

查找在返回值{matched,_,1} ...如果这将是0而不是1(或更多)这意味着没有任何功能符合该模式。 dbg模块的完整文档可以在here找到。

鉴于这两个something/1other:do/1总是返回OK,下面会发生:

6> my_module:run(ok, ok). 
(<0.72.0>) call my_module:run(ok,ok) 
(<0.72.0>) call my_module:something(whatever) 
(<0.72.0>) returned from my_module:something/1 -> ok 
(<0.72.0>) call other:do(more_data) 
(<0.72.0>) returned from other:do/1 -> ok 
(<0.72.0>) returned from my_module:run/2 -> ok 
ok 

在这里,我们可以看到整个呼叫过程,并给出了什么样的返回值。如果我们的东西把它叫做我们知道会失败:

7> my_module:run(error, error). 
** exception error: no match of right hand side value ok 
(<0.72.0>) call my_module:run(error,error) 
(<0.72.0>) call my_module:something(whatever) 
(<0.72.0>) returned from my_module:something/1 -> ok 
(<0.72.0>) exception_from {my_module,run,2} {error,{badmatch,ok}} 

在这里我们可以看到,我们得到了一个badmatch例外,something/1是所谓的,但从来没有这么other:do/1我们可以推断出badmatch这一呼吁之前发生的事情。

熟练使用命令行调试器将为您节省大量时间,您是否调试简单(但棘手!)badmatch错误或更复杂的东西。

希望在Erlang R15出现异常行号的情况下,所有这些都会变得更简单!