Подтвердить что ты не робот

Как отладить код Erlang?

У меня есть некоторый фон Ruby и Java, и я привык иметь точные числа строк в журналах ошибок.

Итак, если в скомпилированном коде есть ошибка, я увижу количество строк, вызвавших исключение в выводе консоли.

Как в этом примере Ruby:

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', как понять, в какой строке проблема?

Кроме того, я попытался переключиться на Emacs + Elang-mode из Vim, но единственным бонусом, который я получил до сих пор, является возможность циклически выполнять ошибки компиляции внутри Emacs (C-k `).

Таким образом, процесс написания кода и поиск простых логических ошибок, таких как "отсутствие соответствия правой стороны", кажется немного громоздким.

Я попытался добавить в код много строк "io: format", но это дополнительная работа, требующая времени.

Я также попытался использовать distel, но для этого нужно всего 10 шагов, чтобы только один раз отлаживать отладчик.

Вопросы:

  • Какой самый простой и простой способ отладки кода Erlang?
  • Есть ли эрланговый режим Emacs с улучшением в плане развития Erlang по сравнению с Vim?
  • Какой цикл "write-compile-debug" вы предпочитаете? Вы оставляете Emacs для компиляции и запуска кода в терминале? Как искать ошибки в коде Erlang?
4b9b3361

Ответ 1

Отладка кода Erlang иногда бывает сложной, особенно в случае ошибок badmatch. В общем, два хороших принципа:

  • Сохраняйте функции короткими
  • Используйте возвращаемые значения напрямую, если можете, вместо привязки временных переменных (это поможет вам получить ошибки function_clause и т.д., Которые будут более информативными)

При этом использование отладчиков обычно требуется, чтобы быстро докопаться до ошибок. Я рекомендую использовать отладчик командной строки, dbg, вместо графического, debugger (это намного быстрее, когда вы знаете, как его использовать, и вам не нужно переключать контекст с оболочки Erlang на GUI).

Учитывая предоставленное вами примерное выражение, часто случается так, что у вас есть не только переменные, назначаемые другим переменным (что абсолютно необязательно в Erlang):

run(X, Y) ->
    X = something(whatever),
    Y = other:thing(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 можно найти здесь.

Учитывая, что something/1 и other:do/1 всегда возвращаются нормально, может произойти следующее:

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

Здесь мы можем увидеть всю процедуру вызова и какие возвращаемые значения были даны. Если мы назовем это с чем-то, что, как мы знаем, потерпит неудачу:

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 ошибки или что-то гораздо более сложное.

Ответ 2

Вы можете использовать отладчик Erlang, чтобы пройти через ваш код и посмотреть, какая строка не работает.

В erl запустите отладчик с помощью

debugger:start().

Затем вы можете выбрать, какие модули вы хотите использовать в интерпретируемом режиме (требуется для отладки) с помощью пользовательского интерфейса или с помощью консоли с ii:

ii(my_module).

Добавление контрольных точек выполняется в пользовательском интерфейсе или консоли снова:

ib(my_module, my_func, func_arity).

Кроме того, в Erlang R15 мы получим номер строки в трассировке стека!

Ответ 3

Если вы замените свою установку erlang на недавнюю, у вас будут номера строк, они будут добавлены начиная с версии 15.

Если новые версии еще не доступны в вашей операционной системе, вы можете создать исходный код или попытаться получить упакованную версию здесь: http://www.erlang-solutions.com/section/132/download-erlang-otp

Ответ 4

Вы можете использовать "debug_info" во время компиляции файла и "отладчик"

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

Подробнее о том, как делать отладку в Erlang, вы можете перейти по ссылке на видео - https://vimeo.com/32724400