D 动态阵列 - RAII
我承认目前我对 D 还没有深入的了解,我的知识完全依赖于我读过的文档和我尝试过的几个例子。
在 C++ 中,您可以依靠 RAII 习惯用法在退出本地作用域时调用对象的析构函数。
可以D吗?
我知道 D 是一种垃圾收集语言,并且它还支持 RAII。 为什么下面的代码在离开作用域时不清理内存?
import std.stdio;
void main() {
{
const int len = 1000 * 1000 * 256; // ~1GiB
int[] arr;
arr.length = len;
arr[] = 99;
}
while (true) {}
}
存在无限循环是为了保持程序打开,使剩余内存分配易于可见。
下面显示了 C++ 中等效的相同程序的比较。
可以看到C++在分配后立即清理了内存(刷新率使得看起来好像少了一些)内存已分配),而 D 保留它,即使它已离开作用域。
那么,GC什么时候进行清理呢?
I admit I have no deep understanding of D at this point, my knowledge relies purely on what documentation I have read and the few examples I have tried.
In C++ you could rely on the RAII idiom to call the destructor of objects on exiting their local scope.
Can you in D?
I understand D is a garbage collected language, and that it also supports RAII.
Why does the following code not cleanup the memory as it leaves a scope then?
import std.stdio;
void main() {
{
const int len = 1000 * 1000 * 256; // ~1GiB
int[] arr;
arr.length = len;
arr[] = 99;
}
while (true) {}
}
The infinite loop is there so as to keep the program open to make residual memory allocations easy visible.
A comparison of a equivalent same program in C++ is shown below.
It can be seen that C++ immediately cleaned up the memory after allocation (the refresh rate makes it appear as if less memory was allocated), whereas D kept it even though it had left scope.
Therefore, when does the GC cleanup?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
scope
声明在 D2 中,所以我不太确定语义,但我想象正在发生的是scope T[] a;
只分配堆栈上的数组结构(不用说,无论范围
如何,这已经发生了)。正如他们所说,不要使用作用域(使用scope(exit)
和朋友 是不同的——继续使用它们)。动态数组总是使用 GC 来分配内存——这是无法回避的。如果您想要更具确定性的东西,请使用
std.container.Array
将是最简单的方式,因为我认为您几乎可以将其放在scope vector3b array
所在的位置:Array!vector3b array
只是不要不必将长度设置为零——一旦超出范围,内存就会被释放(数组在底层使用 libc 中的 malloc/free )。
scope
declarations are going in D2, so I'm not terribly certain on the semantics, but what I'd imagine is happening is thatscope T[] a;
only allocates the array struct on the stack (which needless to say, already happens, regardless ofscope
). As they are going, don't use scope (usingscope(exit)
and friends is different -- keep using them).Dynamic arrays always use the GC to allocate their memory -- there's no getting around that. If you want something more deterministic, using
std.container.Array
would be the simplest manner, as I think you could pretty much drop it in where yourscope vector3b array
is:Array!vector3b array
Just don't bother setting the length to zero -- the memory will be free'd once it goes out of scope (Array uses malloc/free from libc under the hood).
不,您不能假设垃圾收集器会在任何时间点收集您的对象。
但是,有一个
delete
关键字(以及scope
关键字)可以确定性地删除对象。scope
的使用方式如下:delete
的使用方式类似于 C++(delete
没有[]
表示法)。不过,也有一些问题:
它并不总是能正常工作(我听说它不能很好地与数组一起工作)
D 的开发者(例如 Andrei)打算在以后的版本中删除它们,因为如果使用不正确,它显然会弄乱事情。 (我个人讨厌这一点,因为无论如何都很容易把事情搞砸,但他们坚持删除它,而且我认为人们无法说服他们,尽管我很喜欢它如果是这样的话。)
在它的位置,已经有一个
clear
方法可供您使用,例如arr.clear()
;但是,我自己还不太确定它到底做了什么,但是如果您感兴趣,您可以查看 D 运行时中的object.d
中的源代码。至于您的惊讶:我很高兴您感到惊讶,但考虑到它们都是本机代码,这并不奇怪。 :-)
No, you cannot assume that the garbage collector will collect your object at any point in time.
There is, however, a
delete
keyword (as well as ascope
keyword) that can delete an object deterministically.scope
is used like:and
delete
is used like in C++ (there's no[]
notation fordelete
).There are some gotcha's, though:
It doesn't always work properly (I hear it doesn't work well with arrays)
The developers of D (e.g. Andrei) are intending to remove them in later versions, because it can obviously mess up things if used incorrectly. (I personally hate this, given that it's so easy to screw things up anyway, but they're sticking with removing it, and I don't think people can convince them otherwise although I'd love it if that was the case.)
In its place, there is already a
clear
method that you can use, likearr.clear()
; however, I'm not quite sure what it exactly does yet myself, but you could look at the source code inobject.d
in the D runtime if you're interested.As to your amazement: I'm glad you're amazed, but it shouldn't be really surprising considering that they're both native code. :-)