Terminated by signal SIGBUS (Misaligned address error) with ets

Getting

'iex -S mix' terminated by signal SIGBUS (Misaligned address error)

when running

table = :ets.new(:haha, [])

Enum.each(1..4000, fn i -> :ets.insert(table, {to_string(i), i}) end)

known = Enum.map(1..3900, fn i -> to_string(i) end)
{match, _} = Code.eval_quoted(quote(do: :ets.fun2ms(fn {m, n} when m not in unquote(known) -> n end)))

:ets.select(table, match)

on mac.


Or is there maybe some other way to do inverse selection with ets?


Tried ubuntu 18.04, ets fails with the above error too.

1 Like

I suspect the generated match expression is too big

iex(6)> :erts_debug.size(match)
54612 # 436KB? 😰

and it causes memory overflow in ets.

It works fine with small match expressions

iex(8)> known = ["1", "2", "3"]
["1", "2", "3"]
iex(9)> {match, _} = Code.eval_quoted(quote(do: :ets.fun2ms(fn {m, n} when m not in unquote(known) -> n end)))
{[
   {{:"$1", :"$2"},
    [
      not: {:orelse, {:"=:=", :"$1", "2"},
       {:orelse, {:"=:=", :"$1", "3"}, {:"=:=", :"$1", "1"}}}
    ], [:"$2"]}
 ], []}
iex(10)> :ets.select(table, match)
[2806, 1804, 217, 3097, 577, 1347, 2788, 2982, 1023, 608, 2797, 10, 3956, 3925,
 3396, 751, 1406, 3673, 2303, 3199, 1850, 2889, 2448, 484, 562, 2355, 2727,
 2688, 3708, 3116, 257, 2103, 1572, 1168, 3852, 3210, 2817, 1952, 986, 2655,
 1746, 3405, 2686, 1339, 3124, 3253, 3875, 1993, 3286, 2537, ...]

Works with 1..3400

iex(28)> known = Enum.map(1..3400, fn i -> to_string(i) end)
["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14",
 "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27",
 "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40",
 "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", ...]
iex(29)> {match, _} = Code.eval_quoted(quote(do: :ets.fun2ms(fn {m, n} when m not in unquote(known) -> n end)))
{[
   {{:"$1", :"$2"},
    [
      not: {:orelse, {:"=:=", :"$1", "2"},
       {:orelse, {:"=:=", :"$1", "3"},
        {:orelse, {:"=:=", :"$1", "4"},
         {:orelse, {:"=:=", :"$1", "5"},
          {:orelse, {:"=:=", :"$1", "6"},
           {:orelse, {:"=:=", :"$1", "7"},
            {:orelse, {:"=:=", :"$1", "8"},
             {:orelse, {:"=:=", :"$1", "9"},
              {:orelse, {:"=:=", :"$1", "10"},
               {:orelse, {:"=:=", :"$1", "11"},
                {:orelse, {:"=:=", :"$1", "12"},
                 {:orelse, {:"=:=", :"$1", "13"},
                  {:orelse, {:"=:=", :"$1", "14"},
                   {:orelse, {:"=:=", :"$1", "15"},
                    {:orelse, {:"=:=", ...}, {...}}}}}}}}}}}}}}}}
    ], [:"$2"]}
 ], []}
iex(30)> :ets.select(table, match)
[3956, 3925, 3673, 3708, 3852, 3405, 3875, 3501, 3429, 3613, 3743, 3458, 3984,
 3716, 3622, 3644, 3470, 3860, 3632, 3427, 3584, 3647, 3768, 3660, 3428, 3719,
 3725, 3726, 3942, 3658, 3919, 3437, 3723, 3520, 3751, 3735, 3453, 3442, 3580,
 3438, 3712, 3718, 3483, 3642, 3592, 3509, 3486, 3935, 3431, 3559, ...]

but fails with 1..3900

iex(31)> known = Enum.map(1..3900, fn i -> to_string(i) end)
["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14",
 "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27",
 "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40",
 "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", ...]
iex(32)> {match, _} = Code.eval_quoted(quote(do: :ets.fun2ms(fn {m, n} when m not in unquote(known) -> n end)))
{[
   {{:"$1", :"$2"},
    [
      not: {:orelse, {:"=:=", :"$1", "2"},
       {:orelse, {:"=:=", :"$1", "3"},
        {:orelse, {:"=:=", :"$1", "4"},
         {:orelse, {:"=:=", :"$1", "5"},
          {:orelse, {:"=:=", :"$1", "6"},
           {:orelse, {:"=:=", :"$1", "7"},
            {:orelse, {:"=:=", :"$1", "8"},
             {:orelse, {:"=:=", :"$1", "9"},
              {:orelse, {:"=:=", :"$1", "10"},
               {:orelse, {:"=:=", :"$1", "11"},
                {:orelse, {:"=:=", :"$1", "12"},
                 {:orelse, {:"=:=", :"$1", "13"},
                  {:orelse, {:"=:=", :"$1", "14"},
                   {:orelse, {:"=:=", :"$1", "15"},
                    {:orelse, {:"=:=", ...}, {...}}}}}}}}}}}}}}}}
    ], [:"$2"]}
 ], []}
iex(33)> :ets.select(table, match)
fish: 'iex -S mix' terminated by signal SIGBUS (Misaligned address error)

Temporary workaround

table = :ets.new(:haha, [])
Enum.each(1..4000, fn i -> :ets.insert(table, {to_string(i), i}) end)
known = Enum.map(1..3900, fn i -> {:{}, [], [:"=:=", :"$1", to_string(i)]} end)
{orelse, _} = Code.eval_quoted({:{}, [], [:orelse | known]})
match = [{{:"$1", :"$2"}, [not: orelse], [:"$2"]}]
:ets.select(table, match)

https://bugs.erlang.org/browse/ERL-727
https://bugs.erlang.org/browse/ERL-592

1 Like