Порядок уничтожения объектов среды выполнения Visual C ++

Я наткнулся на довольно раздражающую проблему, связанную с тем, когда среда выполнения 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 и это похоже на работу, но поведение этого тоже не определено (я думаю?).

0

Решение

Вы всегда можете сделать refed_list указатель, который инициализируется при запуске. Таким образом, он никогда не будет очищен. (И всякая память, которую она использует, будет восстановлена ​​ОС при выходе из вашего процесса.)

Если это звучит как хак, чтобы обойти более глубокую проблему дизайна, то, вероятно, так и есть. 🙂

2

Другие решения

Я не думаю, что это правда:

Когда моя программа закрывается, среда выполнения очищает refed_list в некоторый момент, и после этого она очищает экземпляры MyClass, вызывая их деструкторы.

Среда выполнения, безусловно, очистит список, но не объекты в списке, потому что они являются указателями. Единственный способ сделать это — использовать класс интеллектуальных указателей, например shared_ptr. Тем не менее, если вы это сделаете, объекты будут пытаться получить доступ к списку во время его уничтожения, что, я не уверен, является неопределенным поведением, но оно, безусловно, кажется шатким.

Возможно, вам следует изменить дизайн, чтобы объекты не ссылались на список, в котором они хранятся, или, по крайней мере, для этого до список уничтожен (и под этим я подразумеваю, прежде чем list :: ~ list даже будет вызван).

0

По вопросам рекламы [email protected]