2011-06-22 7 views
27

Mam trochę tła Ruby i Java i jestem przyzwyczajony do posiadania dokładnej liczby linii w dziennikach błędów.Jak debugować kod Erlang?

Jeśli wystąpi błąd w skompilowanym kodzie, zobaczysz numer linii, która spowodowała wyjątek w wyjściu konsoli.

Podobnie jak w tym przykładzie Ruby:

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

To proste i szybkie - po prostu przejść do linii numer 13 i naprawić błąd.

Wręcz przeciwnie, Erlang prostu mówi coś takiego:

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

Brak numery linii patrzeć.

A jeśli mam dwie linie jak

X = Param1, 
Y = Param2, 

w „my_fun”, jak można zrozumieć, w którym linia leży problem?

Dodatkowo, próbowałem przejść do trybu Emacs + Elang z Vima, ale jedyny bonus, jaki mam do tej pory, to możliwość przechodzenia przez błędy kompilacji wewnątrz Emacsa (C-k `).

Zatem proces pisania kodu i szukania prostych błędów logicznych, takich jak "brak dopasowania po prawej stronie", wydaje się być nieco kłopotliwy.

Próbowałem dodać wiele linii "io: format" w kodzie, ale jest to dodatkowa praca, która wymaga czasu.

Próbowałem również użyć distel, ale wymaga to 10 kroków, aby otworzyć tylko jeden debugger.

Pytania:

  1. Co jest najbardziej prosty i prosty sposób do debugowania kodu Erlang?
  2. Czy tryb erlanga Emacsa ma coś lepszego pod względem rozwoju Erlanga w stosunku do Vima?
  3. Czy preferujesz program "write-compile-debug"? Czy zostawiasz Emacsa do kompilacji i uruchomienia kodu w terminalu? Jak szukać błędów w swoim kodzie Erlang?
+0

Wybierz odpowiedź, na którą rozwiązałeś swoje pytanie, jeśli dotyczy. –

Odpowiedz

17

Możesz użyć Erlang debugger, aby przejrzeć kod i zobaczyć, która linia zawodzi.

Od erl uruchomić debugger z:

debugger:start(). 

Następnie można wybrać, które moduły chcesz w trybie interpretowanym (wymagane do debugowania) za pomocą interfejsu użytkownika lub za pomocą konsoli z II:

ii(my_module). 

Dodawanie punktów przerwania odbywa się w interfejsie lub konsoli ponownie:

ib(my_module, my_func, func_arity). 

Ponadto, w Erlang R15 będziemy wreszcie mieć numer linii w śladach stosu!

+0

Ale nadal myślę, że debugger Erlang jest w fazie rozwoju. Czy jest stabilny? – niting112

+1

Wciąż trwają prace nad debuggerem, ale uważam, że jest wystarczająco stabilny.Używałem go całkiem sporo do debugowania problemów podczas pracy nad RabbitMQ lub związanymi z nim wtyczkami - to całkiem spora część kodu Erlanga. –

+0

@ niting112 Erlang Debugger jest testowanym narzędziem, które jest solidne. Jest to standardowa, przetestowana część dystrybucji. Po wydaniu wersji wx nastąpiły pewne regresje stabilności, ale te zostały już rozwiązane. –

33

Debugowanie kodu Erlang czasami może być trudne, szczególnie w przypadku błędów związanych z badmatch. Ogólnie rzecz biorąc, dwa dobre wytyczne, aby utrzymać to:

  • zachować funkcje krótki
  • Użyj wartości zwracane bezpośrednio, jeśli można, zamiast wiązania zmiennych tymczasowych (to daje korzyści z coraz function_clause błędów itp, które są sposobem więcej informacji)

Z tego powodu, używanie debugerów jest zwykle wymagane, aby szybko dotrzeć do sedna błędów. Zalecam użycie debuggera wiersza poleceń, dbg, zamiast graficznego, debugger (jest znacznie szybciej, gdy wiesz, jak go używać i nie musisz przełączać kontekstu z powłoki Erlang do GUI).

względu na ekspresję próbka podałeś, sprawa jest często, że masz więcej niż tylko zmienne są przypisane do innych zmiennych (co jest absolutnie konieczne w Erlang):

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

debugowania badmatch błąd Oto wspomagane za pomocą debugera wiersza poleceń:

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) 

Poszukaj {matched,_,1} w zwracanej wartości ... jeśli byłoby to 0 zamiast 1 (lub więcej), które oznaczałoby, że żadne funkcje nie pasują do wzorca. Pełna dokumentacja modułu dbg znajduje się pod adresem here.

Biorąc pod uwagę, że zarówno something/1other:do/1 i zawsze wraca ok, może się zdarzyć, co następuje:

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 

Tutaj widzimy całą procedurę połączenia, a co zwracać wartości zostały podane. Jeśli nazywamy to coś wiemy zawiedzie:

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

Tutaj widzimy, że mamy badmatch wyjątek, something/1 nazywano, ale nigdy other:do/1 więc możemy wywnioskować, że badmatch się przed tego połączenia.

Uzyskanie biegłości dzięki debugowaniu wiersza poleceń pozwoli Ci zaoszczędzić sporo czasu, a do tego błędy debugowania (ale trudne!) badmatch lub coś znacznie bardziej złożonego.

Mam nadzieję, że wszystko będzie łatwiejsze, gdy Erlang R15 wyjdzie z numerami linii w wyjątkach!