void main() @nogc
{
scope o = new Object();
}
@nogc
属性确保不使用垃集分配
.
@nogc
属性由编译器强制保证没有堆分配
,因此如果此处不使用带scope
的new
,就会报错.
GC.disable()
是丑陋的.
只要想用类和Phobos
等等,你就会被GC
卡住并激活垃集
.
D的运行时包括许多如在执行main
前初化线程
的基础设施.
可用GC.disable
等等来限制GC
活动,但它仍会在某处激活.
D的GC
是你的朋友,如果不分配
它就不会收集
,除非你想要它.
想避免D运行时,请使用betterC
.
有一些状态如GC
和线程,直到内核进程
结束才会释放.
它不是内存泄漏
,它只是长期存在
的内部状态
.
对于D中的大多数人来说,它在堆栈
上,GC
分配或引用计数
.这三种策略几乎可以保证没有泄漏
.
确定需要
类并且不能使用结构
吗?
如果有子类的最大大小
,也可在堆栈
上的字节数组
中放置任何层次结构实例
.
有一些方法可把类放入堆栈(std.typecons.scoped,emplace()...)
,但不是完全多态的类.
结构
完全支持模板,支持struct S(T){...}
.
没有继承
,但是可用别名本
来欺骗它.
作为BetterC
的替代方案,还可编写
自己的运行时
.
自定义运行时参考.
运行时在运行main
前会分配.但这些都是Cmalloc
分配,而不是GC
分配.这些程序中的GC
使用率应该为零.
分配的72
个字节用于注册甚至在C的main运行
前运行的手动GC
.
分配24
个字节是为了在初化
运行时中添加区间
.
注意,在使用GC
实际分配东西前,它未被初化.相反,它只是直到真正GC
建立时,专门分配该区间
的对象.这不是泄漏
,因为程序退出
时,它仍在使用中.
如在栈上分配
类,类的构造函数
,仍将在堆上分配
,基本上只有顶级类
会在栈上.
最近,Discord
社区中有人寻求帮助,追踪他们使用GC
的D项目中的内存泄漏
.
经过调查,事实
证明泄漏来自C库
,它持有的手动分配
数据比预期
的要长.为了释放
它,用户必须调用
额外库函数
来指示不再需要数据
.
故事寓意:如果担心内存泄漏,GC
是朋友,而不是敌人.😃
import std.stdio;
class A {
int i;
}
class B {
A a;
int i;
this() {
this.a = new A();
}
}
void main() {
scope b = new B();
int i;
writeln("在栈上: ", &i);
writeln("在栈上: ", &b.i);
writeln("在堆上: ", &b.a.i);
}
scope this.a = new A();
呢?
它不会编译.
如果想要所有内容都在栈中,则必须传入a
作为参数,如下所示:
class A {}
class B {
A a;
this(A a) {
this.a = a;
}
}
void main() {
scope a = new A(); //栈上
scope b = new B(a);//栈上
}
之前看到给类中成员
分配空间
的例子,可惜找不到(见下面链接
).然后它跑emplace
来运行构造函数
.这样就不必在顶级栈外
分配它,当有很多成员
时这很烦人.
我个人参与的分配
是模块排序
算法(用于检测
循环和正确排序模块ctor/dtor
).它分配
和释放
临时结构来有向图排序
.
rt_init
分配,应由rt_term
释放,但不是.
我希望可避免
运行时模块
构造函数排序,因为每次都是一样
的,并且会浪费CPU
周期.但这只能在链接后完成.如果可为模块ctor
循环顺序,预先分配
空间,然后在后构建
中编辑
该图,那将是很大改进.
-profile=gc
可跟踪GC
分配.
数据不会从一次
运行到下一次
发生变化,而是无序
存储,然后每次加载
程序时,都必须排序
.每次加载DLL
时,都需要运行此算法
.
在这里,
滚动
到"按成员变量用
"部分.我认为也可按类成员用.
我正在考虑更多链接器
的中间步骤(一旦知道
所有对象),或链接后
步骤.不是运行时
.
如--DRT
开关输出正确排序,然后另一个工具
将其作为输入,然后可正确编辑可执行文件
,或向编译器
提供专门文件,输出预先组织的模块列表
.它们可以是弱符号
,然后只需在其他内容之前链接
目标文件与该数据
?或者,可告诉rt_init
函数:“使用该指针数组
作为列表
,这样就不必排序”.