代码之家  ›  专栏  ›  技术社区  ›  Bob Kaufman

C:按资源分配的相反顺序处理资源是否有好处?

  •  5
  • Bob Kaufman  · 技术社区  · 15 年前

    许多年前,我被告诫尽可能地按照资源分配的相反顺序释放资源。即:

    block1 = malloc( ... );
    block2 = malloc( ... );
    
    ... do stuff ...
    
    free( block2 );
    free( block1 );
    

    我想在一台640K的MS-DOS机器上,这可以最小化堆碎片。在C/.NET应用程序中这样做是否有任何实际的好处,或者这是一个已经超出其相关性的习惯?

    5 回复  |  直到 14 年前
        1
  •  5
  •   Reed Copsey    15 年前

    如果你的资源创建得很好,这就不重要了。

    然而,许多创建不良的库不能进行正确的检查。相反地处理资源分配通常意味着首先要处理依赖于其他资源的资源,这可以防止编写不良的库引起问题。(在本例中,您从不处理资源,然后使用依赖于第一个资源存在的资源。)

    这也是一个很好的实践,因为您不会过早地意外地处理其他对象所需的资源。

    下面是一个例子:查看数据库操作。您不希望在关闭/释放命令(使用连接)之前关闭/释放连接。

        2
  •  4
  •   Will    15 年前

    不用麻烦了。GarbageCollector保留对堆上的对象进行碎片整理和移动的权利,因此不知道它们的顺序。

    此外,如果要释放a和b以及引用b,则在释放a时a是否释放b并不重要,因为Dispose方法应可调用多次,而不会引发异常。

        3
  •  1
  •   Jeffrey L Whitledge    15 年前

    如果您指的是对象上的析构函数被调用的时间,那么这就是垃圾收集器,编程对它的影响很小,并且根据语言定义,它是显式的非确定性的。

    如果要调用IDisposable.Dispose(),则这取决于实现IDisposable接口的对象的行为。

    一般来说,顺序对大多数框架对象来说都不重要,除非它对调用代码很重要。但是,如果对象A保持对对象B的依赖性,并且对象B被释放,那么不使用对象A做某些事情可能非常重要。

    在大多数情况下,Dispose()不是直接调用的,而是作为using或foreach语句的一部分隐式调用的,在这种情况下,根据语句嵌入,自然会出现逆序模式。

    using(Foo foo = new Foo())
    using(FooDoodler fooDoodler = new FooDoodler(foo))
    {
      // do stuff
      // ...
      // fooDoodler automatically gets disposed before foo at the end of the using statement.
    }
    
        4
  •  0
  •   rama-jka toti    15 年前

    嵌套的“using”向你展示了“离经叛道”并不是真的存在,而且很少是这样(在40年的证据之后不要去说永不存在)。其中包括运行在CMOS上的基于堆栈的虚拟机。

    [尽管msdn.com和duffius曾试图使其消失,但您知道要为您管理堆和堆栈之间的差异。多聪明的主意……在太空中]

        5
  •  0
  •   piers7    14 年前

    “运行时不保证调用Finalize方法的顺序。例如,假设有一个对象包含指向内部对象的指针。垃圾收集器检测到两个对象都是垃圾。此外,假设先调用内部对象的Finalize方法。现在,允许外部对象的Finalize方法访问内部对象并对其调用方法,但内部对象已完成,结果可能不可预知。因此,强烈建议Finalize方法不要访问任何内部成员对象。”

    http://msdn.microsoft.com/en-us/magazine/bb985010.aspx

    因此,您可以尽可能多地担心您的LIFO Dispose语义,但是如果您泄漏了一个语义,则将以CLR所希望的任何顺序调用Dispose()。

    (这或多或少就是上面所说的)