我原以为如果我所做的只是1)加载NIF库,2)执行我的新/ 0方法,3)通过F()释放所有内容,然后4)erlang:garbage:collect()我将回到我从记忆方面开始的地方。事实上,我正在泄露记忆。显然,我的代码是最可能的嫌疑人。
有人能告诉我我做错了吗?
我有以下结构:
typedef struct Node
{
int Key;
ERL_NIF_TERM TermPtr;
struct Node *Next;
} Node;
我的负载会打开资源
int on_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
{
ErlNifResourceFlags flags = (ErlNifResourceFlags)(ERL_NIF_RT_CREATE | ERL_NIF_RT_TAKEOVER);
NODE_RESOURCE = enif_open_resource_type(env, "linkedlist_nif",
"node_resource",
&node_dtor,
flags,
0);
}
new / 0映射到此NIF:
static ERL_NIF_TERM new_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ERL_NIF_TERM term;
Node *Head = (Node *)enif_alloc_resource(NODE_RESOURCE,sizeof(Node));
Head->Next = 0;
term = enif_make_resource(env, Head);
enif_release_resource(Head);
return enif_make_tuple2(env, enif_make_atom_len(env, "ok", 2), term);
}
和destruct-或资源如下:
static void node_dtor(ErlNifEnv* env, void* arg)
{
Node* handle = (Node*)arg;
enif_release_resource(handle);
handle = NULL;
}
答案 0 :(得分:3)
因此,在shell中,您使用A = your_nif:new().
创建一个值,然后使用f().
然后使用erlang:garbage_collect().
释放值,并且您希望您的内存使用量与({is})相同在你开始之前?
这可能不会发生,因为shell会保留以前执行结果的历史记录。这将在整个f().
和garbage_collect().
中保持对该术语的引用,因此您将看不到您期望的内存行为。
您可以执行以下操作:
Before = erlang:memory().
Pid = spawn( fun () ->
A = your_nif:new(),
receive
cleanup -> ok
end
end).
timer:sleep(timer:seconds(1)). % Wait for pid to spawn and allocate term.
During = erlang:memory().
Pid ! cleanup.
After = erlang:memory().
lists:zipwith3(fun ({K, B}, {K, D}, {K, A}) ->
{K, _Values = {B, D, A}, {_Leaked = A - B, _Used = D - B}} end,
Before, During, After).
这应该会显示测试期间使用的内存的一些近似值(不严格准确,但如果your_nif:new()
项足够大,它将会超出其他内存分配),并在之后泄露。