跳转至

IDL 究竟在做什么?垃圾回收机制

原文链接:https://www.nv5geospatialsoftware.com/Learn/Blogs/Blog-Details/what-the-bleep-is-idl-doing-garbage-collection

12201 为本文评分:

暂无评分

IDL 究竟在做什么?垃圾回收机制

匿名作者 2014年10月30日,星期四

在 IDL 8.0 版本中,自动垃圾回收机制被引入到 IDL 语言中。它带来了对 IDL 内存使用进行控制的迫切需求缓解。在 IDL 8.0 之前,如果你运行:

obj = obj_new('MyIDLObject')
obj = obj_new('MyOtherIDLObject')

那么第一个 obj 实例就会“泄漏”,这意味着 IDL 无法再访问该内存,并且在 IDL 重启之前这些内存将无法被使用。这在大型应用程序中尤其糟糕,因为“泄漏”的内存会慢慢消耗机器的所有资源。随着垃圾回收机制的加入,一旦第二次调用发生,第一个对象就会被释放,其使用的内存也会被归还给 IDL。因此在 IDL 8.4 中:

IDL> o = obj_new('MyIDLObject') & help,/heap,/brief

Heap Variables:
    # Pointer: 0
    # Object : 1
    # Bytes Heap Memory:  24

IDL> o = obj_new('MyOtherIDLObject') & help,/heap,/brief

Heap Variables:
    # Pointer: 0
    # Object : 1
    # Bytes Heap Memory:  24

然而,考虑以下例子:

        p = plot(/test)
        p = plot(randomu(seed,100))

如果你运行这些语句,尽管看起来 IDL 的垃圾回收机制应该已经释放了第一个 p 实例,但两个绘图窗口都将保持打开状态。IDL 没有释放第一个 p 实例的原因在于一种叫做“引用计数”的机制。为了执行垃圾回收,IDL 需要知道用户何时不再能引用一个对象。所以如果你运行:

a = obj_new('MyIDLObject')
b =  a
help,/heap

IDL 会打印:

Heap Variables:
    # Pointer: 0
    # Object : 1
<ObjHeapVar2>  refcount=2
                STRUCT    = -> MYIDLOBJECT Array[1]

refcount 字段告诉你有多少个 IDL 变量指向同一个对象。一旦 refcount 变为 0,IDL 的垃圾回收机制就会释放该对象。

注意: 使用 OBJ_DESTROY 方法时要非常小心。如果我在 b 上调用 OBJ_DESTROY,那么 a 将不再是一个有效的对象。如果你想要释放对某个对象不必要的引用,请将变量设置为 !NULL 或 0,以避免销毁所有其他引用所指向的对象。

让我们回到 PLOT 的例子。在这种情况下,由于窗口仍然打开,IDL 将 refcount 保持在零以上。在你关闭窗口之前,绘图对象将保持活动状态。你可能会问自己:“好吧,既然 IDL 拥有这个窗口,我该如何重新获取对它的引用呢?因为我真的不是有意丢失我之前对它的引用。”这时 GETWINDOWS() 和 WINDOW(/current) 就派上用场了。假设你运行了以下代码:

p = plot(/test)
p = plot(randomu(seed,100))

哎呀,我们不想丢失对第一个绘图对象的引用!要找回那个引用:首先,点击那个窗口,然后运行:

w = WINDOW(/current)

接着,在窗口内选中绘图对象并运行:

p1 = w.getselect()
help, p1

P1 PLOT <5168>

第一行获取活动窗口的引用。第二行获取绘图对象的引用。类似地,你也可以在不点击任何东西的情况下,使用 GETWINDOWS() 来获取绘图对象的引用:

pwin = GETWINDOWS()

这将返回一个按创建顺序排列的、对所有活动绘图窗口的引用数组。通过索引到所需的窗口,我们可以通过以下方式获取绘图对象的引用:

tool = pwin[0].gettool()
id = igetid('plot',tool=tool)
obj = tool->getbyidentifier(id)
obj->idlitcomponent::getproperty, _proxy=p1
help, p1

P1 PLOT <5168>

通过理解 IDL 对象的生命周期,你可以更好地管理 IDL 使用的内存,并找回那些你可能认为已经丢失的对象。

Vacation Planning, Scientifically Array Uniqueness in IDL