为什么资源管理秩序很重要?

时间:2010-01-18 03:17:16

标签: c++

在Stroustrup的“C ++编程语言”一书中,他提到“资源以与其收购相反的顺序发布通常很重要” 为什么订单很重要?

void acquire()
{
 acquire resource 1;
 ...
 acquire resource n;
 use resources;
 release resource n;
 ...
 release resource 1;
}

那么如果我们改变订单如下呢?

void acquire()
{
   acquire resource 1;
    ...
   acquire resource n;
   use resources;
   release resource 1;
    ...
   release resource n;
}

4 个答案:

答案 0 :(得分:4)

如果不这样做,您可能陷入僵局或泄密状态。假设您声明Obj1并且它分配Obj2-Obj3。你必须释放2和3才能释放1.在实践中虽然这不用担心,因为构造函数和析构函数将按正确的顺序调用。

答案 1 :(得分:3)

一个原因是您通常拥有嵌套的内存分配。

E.g. you have a class 
class A{
  FILE *fp;
  char *name;
  xxx;
}

您首先使用new A为A分配资源,之后您需要操纵A的fpname。因此,当您发布资源时,您需要首先发布fpname,然后发布A

答案 2 :(得分:1)

从最普遍的意义上讲,“只有重要才重要”。依赖性决定了必要的破坏顺序。

此处的现有答案涉及以反向拓扑顺序释放嵌套资源。

但是,C ++还定义了对象内资源的初始化顺序。这意味着会员建设可以使用以前初始化的“兄弟姐妹”......这意味着他们有依赖关系,而这些兄弟姐妹在销毁时仍然有效。

class A {
    A( std::string *link2str );
    ~A();
    std::string *important_state;
};

class B {
    string first; // initialization occurs in the order of declaration
    A second;
    B() : first(), second( &first ) { } // not the constructor's list order
};

不是说这个例子看起来像一个好的设计,但你永远不会知道。 有时成员之间存在某种依赖性的原因。

答案 3 :(得分:0)

实际代码中的资源通常是嵌套的,并且在构建对象时,您希望在销毁它时可用的任何内容。由于C ++具有确定性破坏,因此必须选择一些排序,而FILO(“先进先出”)运行良好。

最简单的嵌套示例是类。它们总是通过首先构建基础,然后是成员,然后是衍生的ctor的身体来构建:

struct Base {
  Base() { cout << "Base\n"; }
};
struct Member {
  Member() { cout << "Member\n"; }
};

struct Derived : Base {
  Member member;
  Derived() { cout << "Derived\n"; }
};

现在您可以在此示例中添加类似的输出dtors。

你不能在Derived被销毁之前销毁Base(Derived的dtor可能需要使用它,以及其他问题);会员也一样。