2013-04-15 18 views
14

Zastanawiam które mogą pewny porządek między zniszczeniem obiektu globalnego i atexit w C++Zamówienie między zniszczeniem obiektu globalnego i atexit w C++

mam globalnego obiektu i zarejestrować atexit funkcja jak poniżej:

static MyClass g_class; 

void onExit() 
{ 
    // do some destruction 
} 

int main() 
{ 
    atexit(onExit); 

    return 0; 
} 

Znalazłem onExit() jest wywoływany przed MyClass::~MyClass() w Visual Studio 2012 i gcc4.7.2. Czy jestem pewien, że onExit jest zawsze wywoływana przed zniszczeniem obiektu globalnego (takiego jak g_class)?

Zastanawiam się, czy w porządku rejestrów obiektów globalnych i atexit stosuje się tę samą tabelę zamówień. Czy nie ma związku między zamówieniem obiektu globalnego a zamówieniem atexit?

Edytowany: Przepraszamy, napisałem błąd. Jestem zdezorientowany podczas porządkowania przykładowego kodu. onExit() jest wywoływana przed ~ MyClass().

+0

Podejrzewam, że zamówienie nie jest w 100% pewne. Dlaczego się przejmujesz? –

+0

Utwórz nowy obiekt globalny przed 'MyClass' i wywołaj' atexit (onExit) 'w jego konstruktorze do sprawdzenia. – lapk

+1

Chcesz kontrolować czas życia obiektów, używaj dynamicznych. – PiotrNycz

Odpowiedz

14

UPDATE:PO poczyniła pewne zamieszanie i wydaje VC11 rzeczywiście nie zachowują się w sposób określony przez C++ 11 Standard. Poniższa odpowiedź została napisana przy założeniu, że tak nie jest.

Dlatego odpowiedź na to pytanie:

Czy jestem pewien, że onExit zawsze jest wywoływana przed globalnego obiektu (jak g_class) zniszczenia?

Czy „Tak”, jak długo pracujesz z kompilatora w pełni zgodny.


Znalazłem MyClass::~MyClass() jest wywoływana przed onExit() w Visual Studio 2012.

Jeśli tak jest, to jest to bug w VC11. Na § 3.6.3/1 C++ 11 Standard:

destruktory (12.4) dla zainicjowanych obiektów (czyli przedmioty, których czas (3.8) jest zapoczątkowane) z pamięci statycznej trwania są nazywane jako wynik powrotu z main oraz w wyniku wywołania std::exit (18,5). [...]

również za § 3.6.3/3:

jeśli zakończenie procesu inicjalizacji obiektu ze statycznymi czas przechowywania sekwencjonuje przed wywołaniem do std::atexit (patrz <cstdlib>, 18,5), wywołanie funkcji przekazanej do std::atexit jest sekwencjonowane przed wywołaniem destruktora dla obiektu.

Dlatego też, w przypadku, onexit() powinny być powoływane przed destruktora MyClass.

O ile mogę powiedzieć, Clang 3.2 i GCC 4.8.0 są zgodne pod tym względem, jak pokazano w tym live example.

+0

To, czy g ++ jest zgodny, czy nie, zależy od opcji kompilatora i platformy. (Jest to zgodne, kiedy może być, ale ponieważ na wielu platformach funkcja 'atexit' jest dostarczana przez platformę, nie zawsze jest to możliwe.) –

+0

Przepraszam. Napisałem błąd. onexit() jest wywoływany przed ~ MyClass. Byłem zdezorientowany podczas porządkowania przykładowego kodu. – zelon

+2

@zelon: OK. Wtedy zachowanie jest poprawne i tak właśnie określa standard C++. –

Powiązane problemy