c - Segmentation fault when calling enif_free() -


i have code should manage 3 dimensional array o(1) access , reading time in erlang. therefor i'm using erlang nifs. working fine except release() function. segmentation fault when calling , have no idea why.

here 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 erlang code (to make arity clearer):

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, testcode:

mutarray:init(), = mutarray:new_3_dim_array(100), mutarray:release(a). 

edit: ok gets more , more weird... after testing fidured out ** exception error: [] if enif_free(data->array); last call of function. @ every other position still segmentation fault, if there println() after enif_free(data->array);. after debugging figured out every line before enif_free(data->array); called. exception seems happen @ enif_free(data->array). know means?

edit2: leaving enif_free(data->array); out doesn't either. segmentation fault well.

i able code running correctly fixing several problems.

first, code assumes it's ok check validity of erl_nif_term comparing null, incorrect. can fix either initializing of array elements 0 (by calling enif_make_int(env, 0) set each element), or using array of structs each struct holds erl_nif_term , unsigned char flag indicate whether term valid or not. if choose latter approach, memset struct values 0, , if caller requests uninitialized element via mutarray:get/4, return enif_make_badarg(env) indicate passed bad arguments call.

second, both set_nif , release functions declared return void when need return erl_nif_term instead. fix can correct return types, , return argv[4] set_nif , enif_make_int(env, 0) release.

lastly, second argument enif_open_resource_type call needs null rather "mutarray" value you're passing, the erl_nif man page indicates.


Comments

Popular posts from this blog

searchKeyword not working in AngularJS filter -

sequelize.js - Sequelize: sort by enum cases -

user interface - how to replace an ongoing process of image capture from another process call over the same ImageLabel in python's GUI TKinter -