2013-01-28 1 views
1

Я написал Erlang C NIF, который возвращает указатель на структуру после вызова new и на данный момент просто увеличивает при вставке переменную. Мне интересно, как правильно уничтожить исходный ресурс или по крайней мере отметить его для GC. Мне не повезло.Правильно освободить память alloced с enif_resource_alloc

#include <stdio.h> 
#include "erl_nif.h" 


typedef struct level { 
    float a; 
    float b; 
} LVL; 

// data array with key being the price 
typedef struct book { 
    int array_size; // # of TTL indices 
    int len; // # of Occupied indices (inc. val) from bestPriceIndex 
    int max_len; 

    LVL lvl_data[]; 

} Book; 


static ErlNifResourceType *MEM_RESOURCE; 


    static int 
on_load(ErlNifEnv *env, void **priv_data, ERL_NIF_TERM load_info) 
{ 
    ErlNifResourceFlags flags = (ErlNifResourceFlags)(ERL_NIF_RT_CREATE); 

    if ((MEM_RESOURCE = enif_open_resource_type(env, 
      NULL, 
      "mem_resource", 
      NULL, //dtor 
      flags, 
      NULL)) == NULL) 
     return -1; 

    return 0; 
} 


    static ERL_NIF_TERM 
new(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) 
{ 
    int max_len = 50; 

    int mem_size = sizeof(Book) + max_len * sizeof(LVL); 
    Book *q = enif_alloc_resource(MEM_RESOURCE, mem_size); 
     if(q == NULL) return enif_make_string(env, "could not alloc", ERL_NIF_LATIN1); 

    q->lvl_data[0].a = 7.0;  

    ERL_NIF_TERM term = enif_make_resource(env, q); 

    enif_release_resource(q); 

    return term; 
}; 


    static ERL_NIF_TERM 
insert(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) 
{ 
    Book *p; 
    if (!enif_get_resource(env, argv[0], MEM_RESOURCE, (void **)&p)) 
     return enif_make_badarg(env); 

    float x = ++p->lvl_data[0].a; 

    return enif_make_string(env, "okk", ERL_NIF_LATIN1); 
}; 


static ErlNifFunc nif_funcs[] = 
{ 
    {"new", 0, new}, 
    {"insert", 1, insert} 
}; 

ERL_NIF_INIT(test, nif_funcs, on_load, NULL, NULL, NULL) 

ответ

1

Когда нет терминов, держащих ресурс, ресурс будет собран автоматически с помощью ОГО.

+0

Я не понимаю, когда или кто держит последний ресурс. Я уже использую enif_release_resource (q); перед возвратом из новой функции. Что еще я должен делать? – BAR

+0

@ user417896: Если вы вернули ресурс с enif_make_resource, то абсолютно ничего. Эрланг использует подсчет ссылок на терминах, чтобы определить, когда больше нет экземпляров термина, плавающего вокруг. Когда это так, автоматически собираются мусор и вызывается ваш деструктор. –

+1

Это относится только к терминам, возвращенным с помощью enif_make_resource; вполне возможно выделить объект ресурса и явно освободить его с помощью enif_release_resource, но после вызова enif_make_resource он управляется памятью. Вы также можете явно опубликовать его, если только один процесс имеет ссылку на этот термин, и этот процесс вызывает nif, который вызывает enif_release_resource. Достаточно сказать, что enif_release_resource уменьшает опорный счетчик, тогда как enif_make_resource увеличивает его. –

 Смежные вопросы

  • Нет связанных вопросов^_^