33

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?
1
  • Please select which answer solved your question, if any. Commented Aug 1, 2011 at 18:51

4 Answers 4

37

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:thing(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:thing(more_data)
(<0.72.0>) returned from other:thing/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, whether you debug simple (but tricky!) badmatch errors or something much more complex.

2
  • How to debug the process which is already running? (rabbitmq, ejabberd) Commented Dec 22, 2021 at 1:06
  • The above examples would trace all existing and new processes in the system. To trace a single process you can supply a pid instead of all (which would trace all processes in the system) like so: dbg:p(Pid, c). If you know a registered name you want to trace, you can use dbg:p(whereis(Name), c). Commented Dec 23, 2021 at 17:40
21

You can use the Erlang debugger to step through your code and see which line is failing.

From erl, start the debugger with:

debugger:start().

Then you can choose which modules you want to in interpreted mode (required for debugging) using the UI or using the console with ii:

ii(my_module).

Adding breakpoints is done in the UI or console again:

ib(my_module, my_func, func_arity).

Also, in Erlang R15 we'll finally have line number in stack traces!

3
  • But still i guess Erlang debugger is under development..Is it stable ?
    – niting112
    Commented Jun 22, 2011 at 11:35
  • 1
    There is still work being done on the debugger, but I find it stable enough to use. I've used it quite a bit to debug problems when I'm working on RabbitMQ or associated plugins - that's a pretty sizable Erlang codebase.
    – Rob Harrop
    Commented Jun 22, 2011 at 12:00
  • @niting112 the Erlang Debugger is a production tested tool that is solid. It is a standard, tested part of the distribution. When the wx version was released there were some stability regressions, but those have since been addressed. Commented Apr 11, 2012 at 0:29
5

If you replace your erlang installation with a recent one, you will have line numbers, they were added starting with version 15.

If the new versions are not yet available on your operating system, you could build from source or try to get a packaged version here: http://www.erlang-solutions.com/section/132/download-erlang-otp

1

You can use "debug_info" at compile time of the file and "debugger"

1> c(test_module, [debug_info]).
{ok, test_module}
2> debugger:start().

More details about how do Debugging in Erlang you can follow by link to video - https://vimeo.com/32724400

2
  • 1
    I get exception error: undefined function debugger:start/0.
    – Damien
    Commented Feb 4, 2023 at 8:42
  • 1
    Installing libwxgtk-webview3.0-gtk3-dev and recompiling Erlang fixed this.
    – Damien
    Commented Feb 4, 2023 at 8:56

Not the answer you're looking for? Browse other questions tagged or ask your own question.