0
点赞
收藏
分享

微信扫一扫

d栈上的类

zibianqu 2022-09-10 阅读 24


原文​ 想在​​栈​​上声明类.
可用​​scope​​存储类,参考

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​​​函数:“使用​​该指针数组​​​作为​​列表​​,这样就不必排序”.

举报

相关推荐

0 条评论