2016-10-26 71 views
2

在我開始之前,我已經檢查出Handle badarg in Erlang 但是我在未定義的檢查中仍然沒有成功,所以我刪除了它們。Erlang「badarg」,不知道如何處理

我建立一個假的銀行過程,並在客戶端執行的平衡查詢支票到銀行的過程中,程序退出時,他說:

Error in process <0.373.0> with exit value: 
{badarg,[{project4,client,3, 
        [{file,"/Users/owner/Desktop/bank.erl"}, 
        {line,27}]}]} 

=ERROR REPORT==== 26-Oct-2016::13:34:57 === 
Error in process <0.379.0> with exit value: 
{badarg,[{project4,client,3, 
        [{file,"/Users/owner/Desktop/bank.erl"}, 
        {line,27}]}]} 

=ERROR REPORT==== 26-Oct-2016::13:34:57 === 
Error in process <0.375.0> with exit value: 
{badarg,[{project4,client,3, 
        [{file,"/Users/owner/Desktop/bank.erl"}, 
        {line,27}]}]} 

=ERROR REPORT==== 26-Oct-2016::13:34:58 === 
Error in process <0.377.0> with exit value: 
{badarg,[{project4,client,3, 
        [{file,"/Users/owner/Desktop/bank.erl"}, 
        {line,27}]}]} 
<0.378.0> Balance request: 54> 
=ERROR REPORT==== 26-Oct-2016::13:34:58 === 
Error in process <0.378.0> with exit value: 
{badarg,[{project4,client,3, 
        [{file,"/Users/owner/Desktop/bank.erl"}, 
        {line,39}]}]} 
<0.372.0> Balance request: 54> 
=ERROR REPORT==== 26-Oct-2016::13:34:58 === 
Error in process <0.372.0> with exit value: 
{badarg,[{project4,client,3, 
        [{file,"/Users/owner/Desktop/bank.erl"}, 
        {line,39}]}]} 

用於模擬的代碼是在這裏:

-module(bankSim). 
-export([start/0, negativeOrPositive/0, sleep/1, generate_rand_int_list/3, generate_rand/2, client/3, clientSpawn/2, bank/2]). 

negativeOrPositive() -> 
    M = rand:uniform(), 
    if 
     M =< 0.5 -> 
      1; 
     true -> 
      -1 
    end. 

sleep(T) -> 
    receive 
     after T -> ok 
    end. 

generate_rand_int_list(N,StartVal,Lim) -> 
    lists:map(fun (_) -> (rand:uniform(Lim-StartVal) + StartVal)* negativeOrPositive() end, lists:seq(1,N)). 

generate_rand(StartVal, Lim) -> 
    rand:uniform(Lim-StartVal) + StartVal. 

client([], _ , BankID) -> 
    BankID ! {goodbye}; 
client([H|T], Count, BankID) -> 
    BankID ! {transaction, self(), H}, 
    receive 
     {Amount, Balance, Success} -> 
      io:format("Client: ~w, Amount requested: ~w, Bank Balance: ~w, Transaction successful ~w ~n",[self(), Amount, Balance, Success]); 
     { X } -> 
      io:format("The balance is ~w ~n", [X]) 
    end,  
    sleep(generate_rand(500, 1500)), 
    Mod = Count rem 5, 
    if 
     Mod == 0 -> 
      io:format("~w Balance request: ",[ self() ]), 
      BankID! {balance, self()}; 
     true -> 
      ok 
    end, 
    client(T, Count + 1, BankID). 

clientSpawn(0, _) -> 
     io:format("Finished spawning clients ~n",[]); 
clientSpawn(N, BankID) -> 
     spawn(bankSim, client, [ generate_rand_int_list(generate_rand(10, 20), 0, 100) , 1, BankID]), 
     clientSpawn(N-1, BankID). 


bank(Balance, 0) -> 
    io:format("Banking simulation ended with a final balance of ~w ~n", [Balance]), 
    io:format("simulation completed ~n", []); 
bank(Balance, NumClients) -> 
    receive 
     {balance, Client} -> 
      Client ! {Balance}; 
     {transaction, Client, Amount} -> 
      NewBalance = Balance + Amount, 
      if 
       NewBalance =< 0 -> 
        Client ! {Amount, NewBalance, no}, 
        bank(Balance, NumClients); 
       NewBalance > 0 -> 
        Client ! {Amount, NewBalance, yes}, 
        bank(NewBalance, NumClients); 
       true -> 
        io:format("This will never be printed") 
      end; 
     goodbye -> 
      NewNumClients = NumClients - 1, 
      bank(Balance, NewNumClients) 
    end. 


start()-> 
    N = generate_rand(2,10), 
    register(bank ,spawn(bankSim, bank, [generate_rand(2000,3000), N])), 
    clientSpawn(N,bank). 

任何幫助,將不勝感激。

+2

看起來您忘記了遞歸調用「{balance,Client}」的消息嗎? (57-58行。) – Dogbert

+0

這似乎奏效了,我一直在盯着它,這麼長時間以來,我可能一直在爲這樣一個簡單的錯誤着迷。 –

回答

6

Erlang的文檔會告訴你,badarg意味着"The argument is of wrong data type, or is otherwise badly formed."這是我從來沒有發現的非常明顯的。

Dogbert指出你在其中一個案例中錯過了遞歸調用bank/2。這是你的badarg的來源 - 但爲什麼?

我一直認爲badarg的含義是「發送給BIF的錯誤參數」。如果你調用一個普通的Erlang函數,你會得到一個function_clause錯誤,這意味着沒有與你的數據匹配的函數子句。

您收到的錯誤消息列出了兩個不同的行號。一個是行

BankID ! {transaction, self(), H}, 

,另一個用於

BankID! {balance, self()}; 

是壞的說法是BankID。不好的原因是因爲它是一個原子,bank。在您的start/0函數中,您生成一個新的銀行進程,然後將該進程的PID註冊爲bank。然後在你的客戶端,你發送消息到bank原子和Erlang解決這個註冊的PID。

它工作了一段時間,但是當你遇到遺漏情況時,你的bank進程終止。現在沒有人註冊原子的後面,並且發送操作員爆炸了,因爲它不能發送到一個不存在的名字。

如果你改變了你的代碼

Bank = spawn(bankSim, bank, [generate_rand(2000,3000), N]), 
clientSpawn(N, Bank). 

那麼你就不會得到badarg,因爲它不是將消息發送到一個沒有人的運行一個PID的錯誤。您可能喜歡嘗試,而不修復循環並查看會發生什麼。

+0

由於您的解釋,我將此標記爲正確,您提供的解決方案也是正確的。感謝您的見解! –

+1

@Nathaniel,關於「我總是認爲badarg是意思」這句話的評論「發送給BIF的壞論點」,「To! Msg'是對使用2個參數的運算符'send'的調用,儘管Erlang的創建者選擇了一個操作符語法來發送消息,但與'global:send(To,Msg)'語法相比,沒有多大區別。非常整齊的答案。 – Pascal

+0

你也會發現,在一些標準庫中,如果參數錯誤,你也會得到'badarg'錯誤。這是明確完成的,因爲它肯定比'function_clause'錯誤或'case_clause'更具信息性,或者由於錯誤參數而可能發生的其他錯誤。 – rvirding

相關問題