[英]Segmentation fault when calling enif_free()
我有一些代碼應該使用Erlang管理O(1)訪問和讀取時間的3維數組。 因此,我正在使用Erlang NIF。 除了release()函數,其他所有東西都工作正常。 調用它時總是會遇到細分錯誤,我也不知道為什么。
這是我的代碼:
#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);
這是我的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.".
順便說一句,這是我的測試代碼:
mutArray:init(),
A = mutArray:new_3_dim_array(100),
mutArray:release(A).
編輯:好吧,它變得越來越怪異...經過一些測試,我弄清楚了我得到** exception error: []
if enif_free(data->array);
是該函數的最后一次調用。 即使在enif_free(data->array);
之后僅存在一個println(),在其他位置我仍然會遇到分段錯誤enif_free(data->array);
。 經過一些調試后,我還發現enif_free(data->array);
之前的每一行enif_free(data->array);
被稱為。 因此,異常似乎發生在enif_free(data->array)
。 有人知道這意味着什么嗎?
EDIT2:只需離開enif_free(data->array);
出去也無濟於事。 我也遇到了細分錯誤。
通過解決幾個問題,我能夠使您的代碼正確運行。
首先,您的代碼假定可以通過將ERL_NIF_TERM
與NULL
比較來檢查ERL_NIF_TERM
的有效性,這是不正確的。 您可以通過以下方法解決此問題:將所有數組元素初始化為0(通過調用enif_make_int(env, 0)
設置每個元素),或使用結構數組,其中每個結構均持有ERL_NIF_TERM
和一個unsigned char
標志以指示是否該術語是否有效。 如果選擇后一種方式,你可以簡單地memset
結構體值設置為0,如果主叫方請求通過一個未初始化的元素mutArray:get/4
,只返回enif_make_badarg(env)
來表示他們通過壞的參數調用。
其次,當set_nif
和release
函數需要返回ERL_NIF_TERM
時,它們都聲明為返回void
。 為了解決這個問題,你可以糾正他們的返回類型,然后再返回argv[4]
從set_nif
和enif_make_int(env, 0)
從release
。
最后,您的enif_open_resource_type
調用的第二個參數需要為NULL
而不是您要傳遞的"mutArray"
值,如erl_nif手冊頁所示。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.