D的所有权与借贷

D的所有权与借贷
问题:泄露(未释放),多次释放,释放后使用
解决方法:在于跟踪哪些指针(拥有内存),哪些指针仅引用内存.它们在哪及哪些指针是活动的.
常用解决方案:
1,垃集.缺点:占用内存大,暂停并减慢代码.可靠(go,java)
2,引用计数,RC对象拥有内存,有个槽保留指向该块内存指针的计数.维护麻烦,异常啊,线程间共享对象的锁啊,为了效率,有时要作弊,临时引用RC对象而不处理计数.
3,手动.快且高,信念.->无法扩展,很难审核.
4,所有权和借贷.优点:高效内存/与手动管理一样性能/可机械审核.缺点:实施.下面讲(ob工作原理,我们(d)如何适应它),纯(传递不变)

所有权

内存,拥有一个所有者.指针是所有者,负责释放.要保证内存中任何可变指针(写指针)都是所指对象的所有者,数据结构中无其他指针,因此构成一棵树.(指针就是所有者,所有者就是指针,但只有唯一的可变指针,类似写指向这块内存),连续块->总是可以表示成树的.借贷(无论何时,仅一个可变指针(拥有者,类似写)指向一块内存,其余为常指针(类似读)(读指针))
同时要求指针都是移动(这样,即所有关系都是一对一).

T* f();
void g(T*);
T* p = f();
T* q = p; //p移动至q,p无效
g(p);//p值无效

不允许把指针移出数据结构,

struct S { T* p; }
S*f();
S*s=f();
T*q=s.p;//不能有两个指向s.p的指针,确保唯一性

此时为什么不标记s.p无效呢?因为有时你想做运行时标记,但这应该是编译时的干的事,所以简单标记其为错误.
让指针离开是错的,即要记着释放.(类似把T*当作T)

void h() {
  T*p = f();
}//错误,忘记释放p?

也可以移出

void g(T*);
void h() {
  T* p = f();
  g(p);  //移至g(),现在由g来负责释放
}//

这干净的解决了内存泄露和使用后释放的问题,
可用释放类比g,分配类比f.
这可通过(类似公共子表达式的)数据流分析来跟踪.
数据流分析可解决到处跑的问题.

上面太严格.

struct S { void car(); void bar(); }
struct S* f();
S* s = f();
s.car();// s移至car()//这里,s要通过借,再还
s.bar();// 错误,s无效了.

d中的结构成员函数按引用,为适应借,可增强为按引用借.
d也支持针.这是对的自然适应.

void g(scope T*);
T* f();
T* p = f();
g(p);// g()借p
g(p);// g返回时可重用p.

当函数按引用或按域指针取参时,不允许转义引用或指针,这适应借语义.
这样借的话,能够保证任意时间段,只存在一个内存对象的指针.
可用常指针进一步增强.
常指针,既不改变,也不释放.这是安全的.常指针活动时,可变指针就禁止活动.类似(读/写)关系.
不复制指针.
还要多理解理解区间.

T* f();
void g(T*);
T* p = f();  // p becomes owner
{
  scope const T* q = p; //借常针,读指针
  scope const T* r = p; //借常针,读指针
  g(p); //错误,有(q,r)时,不能用p.*读时不能写*
}
g(p); // 可用了.

D的函数属性.可以继续添加.不改变现有语法,
@纯 属性,使函数变得纯.ob语义,借贷关系,@活(@live).
ob可按资源,时间需要时渐进加入d代码.可加ob代码,是关键的,使你代码全功能,可测试,可发布.机械保证你的代码内存安全.他让D有新的(借贷)内存安全保证(比如无指向栈转义的指针).

例外

引用计数对象,不能严格ob,引用计数的本质是有多个指向对象的指针,其是内存安全的.他们同ob可以共存而不破坏内存安全.只是不能用ob构建.在@系统中可关闭安全检查,也关闭ob,ob检查器看不见RC实现,因而在ob代码中rc看起来是好代码.需要大量库类型来成功用ob.

结论

对d,这很刺激,我希望能够实现它.
ldc2:新的UDA@ dynamicCompile.动态编译.函数的编译和优化延迟到运行时.可使用主机上可用的指令.
@dynamicCompileConst变量。
您可以使用此属性标记任何全局非线程局部变量。
从静态代码中将它们照常处理,但是如果从@dynamicCompile函数访问时,优化器将它们视为编译时常量。
更详细的在此.

posted @   zjh6  阅读(13)  评论(0编辑  收藏  举报  
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示