如何调试Erlang代码? [英] How to debug Erlang code?

查看:185
本文介绍了如何调试Erlang代码?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些Ruby和Java背景,我习惯于在错误日志中具有确切的行数。



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



像这个Ruby例子一样:

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

它的简单快速 - 我只需转到第13行并修正错误。



相反,Erlang只是说:

  **异常错误:右侧不匹配值[xxxx] 
在函数my_module中:my_fun / 1
从my_module调用:other_fun / 2

没有要查看的行号。



如果我有两行,如

  X = Param1, 
Y = Param2,

在'my_fun'中,怎么能理解哪一行的问题谎言?另外,我试图从Vim切换到Emacs + Elang模式,但到目前为止,唯一的好处就是可以通过编译错误循环Emacs(Ck`)。



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



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



我也尝试使用分发,但需要10步骤只是打开调试器一次。



问题:


  1. 什么是最简单的方法来调试Erlang代码?

  2. 与Vim相比,Emacs的erlang模式在Erlang开发方面有哪些优势?

  3. 你喜欢什么开发编写 - 调试循环?您是否离开Emacs来编译并运行终端中的代码?您如何在Erlang代码中搜索错误?


解决方案

有时候调试Erlang代码可能很棘手,特别是处理 badmatch 错误。一般来说,两个好的指导方针是:




  • 保持功能简短

  • 直接使用返回值如果可以,而不是绑定临时变量(这将使您获得 function_clause 错误等的更多信息)



据说,使用调试器通常需要快速找到错误的底部。我建议使用命令行调试器 dbg ,而不是图形,调试器(当你的速度更快知道如何使用它,并且您不必将上下文从Erlang shell切换到GUI)。



给定您提供的示例表达式,通常情况下你不仅仅是将变量分配给其他变量(这在Erlang中绝对不必要):

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

调试 badmatch 错误是通过使用命令行调试器来帮助的:

  1> dbg:tracer()。 %启动CLI调试器
{ok,< 0.55.0>}
2> dbg:p(all,c)。 %跟踪所有进程,只调用
{ok,[{matched,nonode @ nohost,29}]}
3> dbg:tpl(my_module,something,x)。 %tpl = trace local functions以及
{ok,[{matched,nonode @ nohost,1},{saved,x}]}
4> dbg:tp(other,do,x)。 %tp = trace导出的函数
{ok,[{matched,nonode @ nohost,1},{saved,x}]}
5> dbg:tp(my_module,run,x)。 %x表示打印异常
{ok,[{matched,nonode @ nohost,1},{saved,x}]}%(和正常返回值)
pre>

在返回值中查找 {matched,_,1} 0 而不是 1 (或更多),这意味着没有功能匹配模式。有关 dbg 模块的完整文档可以在这里找到



鉴于 something / 1 other:do / 1 总是返回OK,可能会发生以下情况:

  6> my_module:运行(好的,好的) 
(< 0.72.0>)调用my_module:run(ok,ok)
(< 0.72.0>)调用my_module:something(whatever)
(<0.72.0> ;)从my_module返回:something / 1 - > ok
(< 0.72.0>)调用other:do(more_data)
(< 0.72.0>)从其他方法返回:do / 1 - >从my_module返回的ok
(< 0.72.0>):run / 2 - > ok
ok

这里我们可以看到整个调用过程,并给出了什么返回值。如果我们用一些我们所知道的东西称之为失败:

  7> my_module:run(error,error)。 
**异常错误:右侧没有匹配值ok
(< 0.72.0>)调用my_module:run(error,error)
(< 0.72.0>)调用my_module:从my_module返回的东西(任何)
(< 0.72.0>):something / 1 - > ok
(< 0.72.0>)exception_from {my_module,run,2} {error,{badmatch,ok}}

这里我们可以看到,我们得到一个 badmatch 异常, something / 1 调用,但从不其他:do / 1 ,所以我们可以推断出这个通话之前发生了badmatch。



获取熟练使用命令行调试器将为您节省大量时间,您可以调试简单(但棘手!) badmatch 错误或更复杂的一些。



希望Erlang R15在异常情况下出现的行号会更容易!


I have some Ruby and Java background and I'm accustomed to having exact numbers of lines in the error logs.

So, if there is an error in the compiled code, I will see the number of line which caused the exception in the console output.

Like in this Ruby example:

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

It's simple and fast - I just go to the line number 13 and fix the error.

On the contrary, Erlang just says something like:

** 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

There are no line numbers to look at.

And if I have two lines like

X = Param1,
Y = Param2,

in 'my_fun', how can understand in which line the problem lies?

Additionally, I have tried to switch to Emacs+Elang-mode from Vim, but the only bonus I've got so far is the ability to cycle through compilation errors inside Emacs (C-k `).

So, the process of writing code and seeking for simple logical errors like 'no match of right hand side' seems to be a bit cumbersome.

I have tried to add a lot of "io:format" lines in the code, but it is additional work which takes time.

I have also tried to use distel, but it requires 10 steps to just open a debugger once.

Questions:

  1. What is the most straight and simple way to debug Erlang code?
  2. Does Emacs' erlang-mode has something superior in terms of Erlang development comparing to Vim?
  3. What development 'write-compile-debug' cycle do you prefer? Do you leave Emacs to compile and run the code in the terminal? How do you search for errors in your Erlang code?

解决方案

Debugging Erlang code can be tricky at times, especially dealing with badmatch errors. In general, two good guidelines to keep are:

  • Keep functions short
  • Use return values directly if you can, instead of binding temporary variables (this will give you the benefit of getting function_clause errors etc which are way more informative)

That being said, using the debuggers are usually required to quickly get to the bottom of errors. I recommend to use the command line debugger, dbg, instead of the graphical one, debugger (it's way faster when you know how to use it, and you don't have to context switch from the Erlang shell to a GUI).

Given the sample expression you provided, the case is often that you have more than just variables being assigned to other variables (which is absolutely unnecessary in Erlang):

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

Debugging a badmatch error here is aided by using the command line debugger:

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

Look for {matched,_,1} in the return value... if this would have been 0 instead of 1 (or more) that would have meant that no functions matched the pattern. Full documentation for the dbg module can be found here.

Given that both something/1 and other:do/1 always returns ok, the following could happen:

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

Here we can see the whole call procedure, and what return values were given. If we call it with something we know will fail:

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}}

Here we can see that we got a badmatch exception, something/1 was called, but never other:do/1 so we can deduce that the badmatch happened before that call.

Getting proficient with the command line debugger will save you a lot of time, wether you debug simple (but tricky!) badmatch errors or something much more complex.

Hopefully, all this will be easier when Erlang R15 comes out with line numbers in exceptions!

这篇关于如何调试Erlang代码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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