Visual C ++运行时对象销毁顺序

时间:2013-02-24 10:14:09

标签: c++ visual-c++ object-lifetime

我偶然发现了一个相当烦人的问题,即当程序退出时Visual C ++运行时何时破坏了我的对象。

我有一个用于确保对某些状态的引用有效的类。我需要将状态存储在未知的时间内,在此期间状态可能会被破坏,我无法使用shared_ptr。所以我用

class MyClass
{
private:   
    static std::list<MyClass*> make_list();
    static std::list<MyClass*> refed_list;          
    static void StateClosed(B* state);

public:
    B* state;
    MyClass(B* state);
    virtual ~MyClass();

    bool still_valid() const;
 };

MyClass的每个实例在其构造函数中将自身添加到refed_list,并在其析构函数中删除自身。如果封装状态被关闭,则通知MyClass并检查refed_list封装实例并使其指针无效。这不是真正相关的,重要的是它使用static list并且它在构造函数/析构函数中访问此列表。我在定义refed_list的文件中初始化MyClass

现在,问题..当我的程序关闭时,运行时会在某个时刻清除refed_list,然后清除MyClass的实例,调用它们的析构函数。然后他们尝试访问已经清理过的refed_list。这导致我的迭代器不正确,我得到未定义的行为,在这种情况下调试断言失败。

有没有解决这个问题的方法?我怀疑我可以指定不同编译单元中的哪些订单对象被破坏,但有没有办法检查refed_list是否仍然有效?目前我检查refed_list.size() == 0是否有效,但它的行为也未定义(我认为?)。

2 个答案:

答案 0 :(得分:2)

您始终可以使refed_list指针在启动时初始化。这样它永远不会被清理干净。 (当你的进程退出时,操作系统将恢复它使用的任何内存。)

如果这听起来像是一个解决更深层设计问题的黑客,那么可能就是这样。 :)

答案 1 :(得分:0)

我不认为这是真的:

  

当我的程序关闭时,运行时会在某个时刻清除refed_list,然后清理MyClass的实例,调用它们的析构函数。

运行时肯定会清理列表,但不会清除列表中的对象,因为它们是指针。唯一的方法是使用像shared_ptr这样的智能指针类。尽管如此,如果你这样做,对象会在它被销毁时尝试访问列表,我不确定它是不确定的行为,但它肯定看起来不稳定。

也许您应该重新设计它,以便对象不需要引用它们存储的列表,或者至少在之前列表被销毁(并且我的意思是)在list :: ~list之前甚至被调用。)