【问题标题】:D Dynamic Arrays - RAIID 动态阵列 - RAII
【发布时间】:2011-05-24 04:23:34
【问题描述】:

我承认我目前对 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 清理呢?

【问题讨论】:

    标签: memory-management garbage-collection d raii


    【解决方案1】:

    scope 声明在 D2 中,所以我不太确定语义,但我想象正在发生的是 scope T[] a; 只在堆栈上分配数组结构(不用说,已经发生了,不管scope)。在他们进行的过程中,不要使用范围(使用scope(exit) and friends 是不同的——继续使用它们)。

    动态数组总是使用 GC 来分配它们的内存——没有办法解决这个问题。如果你想要更确定的东西,使用std.container.Array 将是最简单的方式,因为我认为你几乎可以将它放在你的scope vector3b array 所在的位置:

    Array!vector3b array

    不要费心将长度设置为零——一旦超出范围,内存将被释放(数组使用 malloc/free from libc under the hood)。

    【讨论】:

      【解决方案2】:

      不,您不能 假设垃圾收集器会在任何时间点收集您的对象。

      但是,delete 关键字(以及 scope 关键字)可以确定性地删除对象。

      scope 的用法如下:

      {
          scope auto obj = new int[5];
          //....
      } //obj cleaned up here
      

      delete 的使用方式与 C++ 中一样(delete 没有 [] 符号)。

      不过也有一些陷阱:

      • 它并不总是能正常工作(我听说它不适用于数组)

      • D 的开发人员(例如 Andrei)打算在以后的版本中删除它们,因为如果使用不当,它显然会搞砸事情。 (我个人讨厌这个,因为无论如何都很容易把事情搞砸,但他们坚持删除它,我认为人们无法说服他们,尽管我很喜欢它如果是这样的话。)

      • 已经有一个clear 方法可以使用,例如arr.clear();不过,我自己还不太清楚它到底做了什么,但如果您有兴趣,可以查看 D 运行时中 object.d 中的源代码。


      至于您的惊讶:我很高兴您感到惊讶,但考虑到它们都是本机代码,这并不奇怪。 :-)

      【讨论】:

      • 如果我不能假设 GC 会清理未使用的内存,我怎么能假设我的程序不会立即耗尽内存?例如,如果我将 vector3b 动态数组的两个 2.25GB 块(不同范围)打包,我会立即耗尽内存,即使 GC 应该将第一个识别为未使用(每个 RAII)?
      • 另外,为什么非动态数组也会出现同样的问题,不应该遵循RAII吗?即使由于大小,它们也可能是堆分配的。
      • @Daniel:不,我的意思是,你不能假设它会在任何特定时间发生;它会发生某个时候,但你不知道什么时候。此外,这取决于您所说的非动态数组是什么意思。您现在看到的是 not 数组,但它们是 slices (只是长度-指针对)。数组本身位于堆内存中,您的 slices 的行为与任何其他变量一样——它们没有析构函数,但如果有,它会在它们被释放时运行。所以如果你使用 Array 类型,它会自行销毁,因为它有一个析构函数。
      • @Daniel:请参阅 this page 了解有关切片如何工作的说明。
      • 作用域和删除都将在 D2 中被弃用。
      猜你喜欢
      • 2020-11-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-18
      • 2020-12-24
      • 2017-02-15
      • 1970-01-01
      相关资源
      最近更新 更多