0

I am working on integrating a C++ api with Elixir, by using NIFs. Now whenever I load the NIF, I want to initialize some variables/data which will be persisted across NIF calls. I was trying to achieve the same by load function mentioned in the ERL_NIF_INIT call. But I am observing some weird behavior out of load function. Please have a look at the below mentioned example and then I’ll explain the issue further:

#include <erl_nif.h>

static ERL_NIF_TERM sample(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
  return enif_make_atom(env, "ok");
}

static ErlNifFunc nif_funcs[] = {{"sample", 1, sample}};

static int load(ErlNifEnv *env, void **priv_data, ERL_NIF_TERM load_info) {
  try {
    1 / 0; // nif loads if this is the case
    int x = 1 / 0; // float point exception segmentation fault when used this line
  } catch (...) {
    return 1;
  }
  return 0;
}

ERL_NIF_INIT(Elixir.Sample, nif_funcs, load, NULL, NULL, NULL);

Now closely observe the load function containing the try/catch block, when I use 1 / 0; expression in the body of try block, NIF is loaded but when the expression 1 / 0; is replaced by int x = 1 / 0; erlang vm fails to load NIF and crashes with floating point exception segmentation fault even if I have added the try/catch block to handle the exception. Can someone explain this to me? I really need help here.

Here is the elixir code used for interfacing:

defmodule Sample do
  @on_load :load_nifs

  def load_nifs do
    :ok =
      :sample
      |> :code.priv_dir()
      |> Path.join("sample")
      |> :erlang.load_nif("0.0.1")
  end

  def sample(_) do
    raise "sample/1 Function not implemented"
  end
end

Command used to compile NIF g++ -fPIC -shared sample.cpp -o sample.so

P.S. - Thanks for your time to read this, I really appreciate it.

  • The explanation is simple -- dividing by zero is not a C++ exception. You have to check this the old-fashioned way by testing the denominator. – PaulMcKenzie May 12 '21 at 18:51
  • Ah I see! Also If that's the case then why `1 / 0;` expression works when it is not assigned to any variable? Is it because of compiler removing the statement as it's output is not used anywhere in one of those code optimization steps? – Shubham Singh May 12 '21 at 19:08
  • Even if you were to assign it to a variable, it still will not generate a C++ exception. Maybe some other system level or OS exception, but not a C++ exception. The C++ language specification lists where the C++ language must throw an exception for certain conditions (`std::vector::at()`, for example). Dividing by zero is not one of those conditions that throws a C++ exception. – PaulMcKenzie May 12 '21 at 19:50

0 Answers0