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

Visual C++ runtime object destruction order

本文关键字:顺序 对象 C++ 运行时 Visual      更新时间:2023-10-16

我偶然发现了一个相当烦人的问题,这个问题与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,并在构造函数/析构函数中访问该列表。我在定义MyClass的文件中初始化refed_list

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

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

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

如果这听起来像是解决更深层次设计问题的破解方法,那么它可能是。:)

我不认为这是真的:

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

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

也许你应该重新设计它,这样对象就不需要引用存储它们的列表,或者至少在列表被销毁之前(我指的是在list::~list被调用之前)执行