0

我偶然发现了一个相当烦人的问题,它与 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封装实例并使其指针无效。这并不相关,重要的是它使用 astatic list并且它在构造函数/析构函数中访问此列表。refed_list我在定义的文件中初始化MyClass

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

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

4

2 回答 2

2

You can always make refed_list a pointer that is initialised on start up. That way it will never be cleaned up. (And any memory it uses will be recovered by the OS when your process exits.)

If that sounds like a hack to work around a deeper design problem, then it probably is. :)

于 2013-02-24T11:31:39.360 回答
0

我不认为这是真的:

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

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

Perhaps you should redesign it so that the objects don't need to reference the list where they're stored, or at least to do it before the list is destroyed (and by that I mean before list::~list is even called).

于 2013-02-24T11:08:14.570 回答