Search code examples
eclipsecompiler-errorsformatargumentserlang

How to solve the problem with erlang badarg?


I ran the code below in Eclipse. The code is compiled and the .txt file is created in the scr folder in the workspace in Eclipse with the header of the data passed to the first io:format, but the second io:format throws the error of bad argument and I can't figure out how to solve it.

%% @author PC
%% @doc @todo Add description to pingping.

-module(pingping).
-export([run/2, run/3]).
-include("conf.hrl").

run(DataSize, R) ->
    OutFileLocation = "out_cerl_pingping.txt",
    case file:open(OutFileLocation, [append]) of
        {error, Why} ->
            ?ERR_REPORT("L'archivio non esiste!", Why);
        {ok, OutFile} ->
            run(DataSize, R, OutFile)
    end.

run(DataSize, R, OutFile) ->
    Data = generate_data(DataSize),
    Self = self(),
    SpawnStart = time_microseg(),
    P1 = spawn(fun() -> pingping(Data, Self, R) end),
    P2 = spawn(fun() -> pingping(Data, Self, R) end),
    SpawnEnd = time_microseg(),
    TimeStart = time_microseg(),
    P1 ! {init, self(), P2},
    P2 ! {init, self(), P1},
    finalize(P1),
    finalize(P2),
    TimeEnd = time_microseg(),
    TotalTime = TimeEnd - TimeStart,
    SpawnTime = SpawnEnd - SpawnStart,
    printResult(Data, R, TotalTime, SpawnTime, OutFile).

pingping(_, Parent, 0) ->
    Parent ! {finish, self()};
pingping(Data, Parent, R) ->
    receive
        {init, Parent, Peer} ->
            Peer ! {self(), Data},
            pingping(Data, Parent, R-1);
        {Peer, _} ->
            Peer ! {self(), Data},
            pingping(Data, Parent, R-1)
    end.

finalize(Pid) ->
    receive
        {finish, Pid} -> ok
    end.

printResult(Data, R, Time_exec, Time_spawn, OutFile) ->
    FormatH = "~-9s\t ~-13s\t ~-22s\t ~-11s\t ~-10s~n",
    Header = ["#bytes", "#repetitions", "exec_time[microsec]", "MBytes/sec", "spawn_time"],
    io:format(OutFile, FormatH, Header),
    MBps = bandwidth_calc(Data, Time_exec),
    FormatD = "~-9w\t ~-13w\t ~-22f\t ~-11f\t ~-3f~n",
    io:format(OutFile,FormatD, [size(Data), R, Time_exec, MBps, Time_spawn ]).

bandwidth_calc(Data, Time) ->
    Megabytes = (size(Data) / math:pow(2, 20)),
    Seconds = (Time * 1.0e-6),
    Megabytes / Seconds.

generate_data(Size) -> generate_data(Size, []).
generate_data(0, Bytes) ->
    list_to_binary(Bytes);
generate_data(Size, Bytes) ->
    generate_data(Size - 1, [1 | Bytes]).

time_microseg() ->
    {MS, S, US} = now(),
    (MS * trunc(1.0e+12)) + (S * trunc(1.0e+6)) + US.

%-define(OUT_FILE, "erl_out.txt").

-define(ERR_REPORT(Msg, Reason), io:format("%%%%%%%%%%%%%% ERROR %%%%%%%%%%%%%%\n" ++
                     "Msg: ~s\n" ++
                     "Reason: ~s\n\n", [Msg, Reason])).

Solution

  • Your code can't be compiled since the conf.hrl include file isn't shown, so I'm guessing it supplies the ERR_REPORT macro provided at the bottom. You didn't include instructions on how to run the code, so I guessed and called pingping:run(3, 3)., which resulted in this error under Erlang/OTP 26.1:

    ** exception error: bad argument
         in function  io:format/3
            called as io:format(<0.95.0>,"~-9w\t ~-13w\t ~-22f\t ~-11f\t ~-3f~n",
                                [3,3,23,0.12439230213994565,6])
            *** argument 3: element 3 must be of type float
                            element 5 must be of type float
    

    The error message gives us the answer: you're trying to print integers as floats. Changing this line:

    FormatD = "~-9w\t ~-13w\t ~-22f\t ~-11f\t ~-3f~n",
    

    to the following in order to correct the formatting for elements 3 and 5:

    FormatD = "~-9w\t ~-13w\t ~-22w\t ~-11f\t ~-3w~n",
    

    results in pingping:run(3, 3) returning ok and the out_cerl_pingping.txt file containing the following:

    #bytes       #repetitions    exec_time[microsec]     MBytes/sec      spawn_time
    3            3               15                      0.190735        5