[英]Segmentation fault when calling enif_free()
I have some code that should manage a 3 dimensional array with O(1) access and reading time in Erlang. 我有一些代码应该使用Erlang管理O(1)访问和读取时间的3维数组。 Therefor I'm using Erlang NIFs.
因此,我正在使用Erlang NIF。 Everything is working fine except for the release() function.
除了release()函数,其他所有东西都工作正常。 I always get a segmentation fault when calling it and I have no idea why.
调用它时总是会遇到细分错误,我也不知道为什么。
Here is my code: 这是我的代码:
#include "erl_nif.h"
static ErlNifResourceType *DATA_RESOURCE;
typedef struct
{
int size;
ERL_NIF_TERM *** array;
ERL_NIF_TERM defaultValue;
} DATA;
static ERL_NIF_TERM new3DimArray(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
DATA *data = (DATA *)enif_alloc_resource(DATA_RESOURCE, sizeof(DATA));
int size;
enif_get_int(env, argv[0], &size);
if(argc > 1)
{
data->defaultValue = argv[1];
}else{
data->defaultValue = NULL;
}
data->size = size;
data->array = (ERL_NIF_TERM ***)enif_alloc(sizeof(ERL_NIF_TERM **) * size);
int x = 0;
while(x < size)
{
data->array[x] = (ERL_NIF_TERM **)enif_alloc(sizeof(ERL_NIF_TERM *) * size);
int y = 0;
while(y < size)
{
data->array[x][y] = (ERL_NIF_TERM *)enif_alloc(sizeof(ERL_NIF_TERM) * size);
y++;
}
x++;
}
return enif_make_resource(env, data);
}
static ERL_NIF_TERM get_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
DATA *data;
enif_get_resource(env, argv[0], DATA_RESOURCE, &data);
int x;
int y;
int z;
enif_get_int(env, argv[1], &x);
enif_get_int(env, argv[2], &y);
enif_get_int(env, argv[3], &z);
ERL_NIF_TERM res = data->array[x][y][z];
if(res == NULL && data->defaultValue != NULL)
{
res = data->defaultValue;
}
return res;
}
static void set_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
DATA *data;
enif_get_resource(env, argv[0], DATA_RESOURCE, &data);
int x;
int y;
int z;
enif_get_int(env, argv[1], &x);
enif_get_int(env, argv[2], &y);
enif_get_int(env, argv[3], &z);
ERL_NIF_TERM value = argv[4];
data->array[x][y][z] = value;
}
static void release(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
DATA *data;
enif_get_resource(env, argv[0], DATA_RESOURCE, &data);
int x = 0;
while(x < data->size)
{
int y = 0;
while(y < data->size)
{
enif_free(data->array[x][y]);
y++;
}
enif_free(data->array[x]);
x++;
}
enif_free(data->array);
enif_release_resource(data);
}
static void cleanup(ErlNifEnv *env, void *obj){}
static int load(ErlNifEnv *env, void **priv_data, ERL_NIF_TERM load_info){
DATA_RESOURCE = enif_open_resource_type(env, "mutArray", "DATA_RESOURCE", &cleanup, ERL_NIF_RT_CREATE, 0);
return 0;
}
static ErlNifFunc nif_funcs[] = {
{"new_3_dim_array", 1, new3DimArray},
{"new_3_dim_array", 2, new3DimArray},
{"get", 4, get_nif},
{"set", 5, set_nif},
{"release", 1, release}
};
ERL_NIF_INIT(mutArray, nif_funcs, load, NULL, NULL, NULL);
This is my Erlang code (to make the arity clearer): 这是我的Erlang代码(以使Arity更清晰):
module(mutArray).
%% ====================================================================
%% API functions
%% ====================================================================
-export([init/0, new_3_dim_array/1, new_3_dim_array/2, get/4, set/5, release/1]).
init() ->
erlang:load_nif("./mutArray", 0).
new_3_dim_array(_Size) ->
"NIF not loaded yet.".
new_3_dim_array(_Size, _DefaultValue) ->
"NIF not loaded yet.".
get(_Array, _X, _Y, _Z) ->
"NIF not loaded yet.".
set(_Array, _X, _Y, _Z, _Value) ->
"NIF not loaded yet.".
release(_Array) ->
"NIF not loaded yet.".
Btw, this is my Testcode: 顺便说一句,这是我的测试代码:
mutArray:init(),
A = mutArray:new_3_dim_array(100),
mutArray:release(A).
EDIT: Ok it gets more and more weird... After some testing I fidured out that I get ** exception error: []
if enif_free(data->array);
编辑:好吧,它变得越来越怪异...经过一些测试,我弄清楚了我得到
** exception error: []
if enif_free(data->array);
is the last call of the function. 是该函数的最后一次调用。 At every other position I still get the segmentation fault, even if there is just a println() after
enif_free(data->array);
即使在
enif_free(data->array);
之后仅存在一个println(),在其他位置我仍然会遇到分段错误enif_free(data->array);
. 。 After some debugging I also figured out that every line before
enif_free(data->array);
经过一些调试后,我还发现
enif_free(data->array);
之前的每一行enif_free(data->array);
was called. 被称为。 So the exception seems to happen at
enif_free(data->array)
. 因此,异常似乎发生在
enif_free(data->array)
。 Does anybody know what this means? 有人知道这意味着什么吗?
EDIT2: Simply leaving enif_free(data->array);
EDIT2:只需离开
enif_free(data->array);
out doesn't help either. 出去也无济于事。 I get a segmentation fault then as well.
我也遇到了细分错误。
I was able to get your code running correctly by fixing several problems. 通过解决几个问题,我能够使您的代码正确运行。
First, your code assumes that it's OK to check the validity of an ERL_NIF_TERM
by comparing it to NULL
, which is incorrect. 首先,您的代码假定可以通过将
ERL_NIF_TERM
与NULL
比较来检查ERL_NIF_TERM
的有效性,这是不正确的。 You can fix this by either initializing all of your array elements to 0 (by calling enif_make_int(env, 0)
to set each element), or by using an array of structs where each struct holds an ERL_NIF_TERM
and an unsigned char
flag to indicate whether the term is valid or not. 您可以通过以下方法解决此问题:将所有数组元素初始化为0(通过调用
enif_make_int(env, 0)
设置每个元素),或使用结构数组,其中每个结构均持有ERL_NIF_TERM
和一个unsigned char
标志以指示是否该术语是否有效。 If you choose the latter approach, you could simply memset
the struct values to 0, and if a caller requests an uninitialized element via mutArray:get/4
, just return enif_make_badarg(env)
to indicate they passed bad arguments to the call. 如果选择后一种方式,你可以简单地
memset
结构体值设置为0,如果主叫方请求通过一个未初始化的元素mutArray:get/4
,只返回enif_make_badarg(env)
来表示他们通过坏的参数调用。
Second, both your set_nif
and release
functions are declared to return void
when they need to return ERL_NIF_TERM
instead. 其次,当
set_nif
和release
函数需要返回ERL_NIF_TERM
时,它们都声明为返回void
。 To fix this you can correct their return types, and then return argv[4]
from set_nif
and enif_make_int(env, 0)
from release
. 为了解决这个问题,你可以纠正他们的返回类型,然后再返回
argv[4]
从set_nif
和enif_make_int(env, 0)
从release
。
Lastly, the second argument to your enif_open_resource_type
call needs to be NULL
rather than the "mutArray"
value you're passing, as the erl_nif man page indicates. 最后,您的
enif_open_resource_type
调用的第二个参数需要为NULL
而不是您要传递的"mutArray"
值,如erl_nif手册页所示。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.