内存管理

Silk采用引用计数管理内存对象,当引用计数为0时自动回收内存,所以通常情况下用户无需关心内存的分配与释放。
但引用计数如遇到循环引用会产生无法回收内存的问题,从而导致内存泄漏。所以在使用对象(数组,字典,类)时应避免引起循环引用的问题。

何为循环引用
循环引用是对象之间互相引用,如:对象A引用对象B,对象B引用对象C,而对象C又反过来引用对象A。
下面代码将造成循环引用,导致Silk最后无法回收A,B和C的内存:
    A={"value":1};
    B={"value":2};
    C={"value":3};
    A["next"]=B;//A的next指向B
    B["next"]=C;//B的next指向C
    C["next"]=A;//C的next指向A,形成A->B->C->A的循环引用
 

对象引用自身也将会造成循环引用:
main()
{
    arr=[];
    arr.append(arr);//自己加自己形成循环引用
}

解决循环引用问题
Silk为对象(数组,字典,类)提供了弱引用函数_getptr()_restore(ptr)以解决循环引用问题。
_getptr()函数返回对象句柄(内存中的位置),但不会增加引用计数,所以在循环的某个节点上采用弱引用即可解除循环引用。
_restore(ptr)函数根据对象句柄ptr恢复并返回对象。
main()
{
    A={"value":1};
    B={"value":2};
    C={"value":3};
    A["next"]=B;//A的next指向B
    B["next"]=C;//B的next指向C
    C["next"]=A._getptr();//弱引用函数_getptr返回A的句柄,C的next指向A的句柄,所以不会形成循环引用
    
    a=C._restore(C["next"]);//根据C的next中A的句柄恢复A对象
    print(a["value"]);//打印A的值
    
    arr=[];
    arr.append(arr._getptr());//加对象的句柄,而不是对象自身
}
上面代码形成循环,但不会造成循环引用,所以对象A,B,C和arr的内存将被顺利回收。