Порядок между уничтожением глобального объекта и atexit в С++ - программирование
Подтвердить что ты не робот

Порядок между уничтожением глобального объекта и atexit в С++

Интересно, может ли быть уверен порядок между уничтожением глобального объекта и atexit в С++

У меня есть глобальный объект и зарегистрируйте функцию atexit, как показано ниже:

static MyClass g_class;

void onExit()
{
    // do some destruction
}

int main()
{
    atexit(onExit);

    return 0;
}

Я обнаружил, что onExit() вызывается перед MyClass::~MyClass() в Visual Studio 2012 и gcc4.7.2. Я уверен, что onExit всегда вызывается перед уничтожением глобального объекта (например, g_class)?

Интересно, что порядок регистра объектов объекта и порядок регистрации atexit используют одну и ту же таблицу заказов. Или нет связи между глобальным порядком объектов и порядком atexit?

Отредактировано: Sorry, я написал ошибку. Я так запутался, приведя пример кода. onExit() вызывается перед ~ MyClass().

4b9b3361

Ответ 1

ОБНОВЛЕНИЕ: OP сделал некоторую путаницу, и кажется, что VC11 действительно ведет себя так, как это определено стандартом С++ 11. Следующий ответ был написан в предположении, что он этого не сделал.

Поэтому ответ на этот вопрос:

Я уверен, что onExit всегда вызывается перед уничтожением глобального объекта (например, g_class)?

Является "Да" , если вы работаете с полностью совместимым компилятором.


Я обнаружил, что MyClass::~MyClass() вызывается перед onExit() в Visual Studio 2012.

Если это так, то это ошибка в VC11. В пункте 3.6.3/1 стандарта С++ 11:

Деструкторы (12.4) для инициализированных объектов (т.е. объекты, чье жизненное время (3.8) началось) со статическим хранилищем длительность вызывается в результате возврата из main и в результате вызова std::exit (18.5). [...]

Кроме того, в пункте 3.6.3/3:

Если завершение инициализации объекта со статической продолжительностью хранения секвенируется перед вызовом до std::atexit (см. <cstdlib>, 18.5), вызов функции, переданной в std::atexit, секвенирован перед вызовом деструктора для объекта.

Следовательно, в вашем случае перед деструктором MyClass следует вызвать onExit().

Насколько я могу судить, Clang 3.2 и GCC 4.8.0 совместимы в этом отношении, как показано в этом живом примере.