2011-06-22 153 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出現異常行號的情況下,所有這些都會變得更簡單!