Атексит для уничтожения одиночного: случай неудачи

От : https://sourcemaking.com/design_patterns/to_kill_a_singleton

Одно можно сказать наверняка: вы не можете использовать более одного разрушителя, если
Синглтонные деструкторы зависят друг от друга. Альтернативой является
полностью избегать эсминцев и вместо этого полагаться на проект стандарта
Функция atexit (), как предложил мне Тим Пайерлс: я утверждаю, что
atexit () — это хороший способ очистки синглетонов в C ++, когда вы действительно
хотите единичные экземпляры с продолжительностью жизни программы и без замены.

Проект стандарта обещает многое: функция atexit () может быть
используется для указания функции, вызываемой при выходе. Если atexit () должен быть
вызывается, реализация не должна уничтожать инициализированные объекты
до вызова atexit () до тех пор, пока функция, указанная в
Вызов atexit () был вызван.

Единственный способ увидеть этот сбой — статически инициализированный
инициализируется объект, деструктор которого зависит от экземпляра Singleton
после экземпляр Singleton создается, то есть, посредством некоторой другой статической инициализации. Это говорит о том, что классы, имеющие статические
экземпляры следует избегать зависимости от синглетонов при уничтожении. (Или же
по крайней мере, для таких классов должен быть способ проверить
Существование Синглтона при уничтожении.)

Я не мог понять последний абзац, то есть, в каком случае он потерпит неудачу и как.

Может кто-нибудь, пожалуйста, пролить свет на это.

0

Решение

Так как это использует atexit вместо деструкторов для очистки Singletons, порядок очистки объекта может быть изменен. Например:

Singleton S;
Object O;
// later in code:
Call atexit() to register cleanup function for S

Обычно порядок уничтожения этих объектов будет O, затем S, но с atexit вызов добавил, что это обратный, так что S очищается в atexit звоните, тогда O уничтожается. Если деструктор O каким-либо образом зависит от Singleton S, вы будете иметь неопределенное поведение во время работы этого деструктора.

Чтобы избежать этого, нужно позвонить atexit зарегистрировать функцию очистки Singleton перед созданием любых объектов, которые зависят от нее. Если O сам является статическим объектом, это может быть сложно и может потребовать создания класса, конструктор которого вызывает atexit поэтому его можно вставить между двумя статическими объектами.

Singleton S;
struct SAtExit {
SAtExit() { atexit(...); }
} SCleanup;
Object O;
1

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

Других решений пока нет …