2009-05-27 11 views
10

Istnieją różne sposoby kończenia procesu:różne sposoby kończenia procesu C++

np .: ExitProcess, ExitThread (z głównym gwintem), wyjścia, przerwanie, powrót z głównym wypowiedzieć.

Chciałbym poznać wpływ każdej z metod na statyczne/globalne/automatyczne niszczenie obiektów.

Na przykład mam projekt, który zawiesza się (prawdopodobnie z powodu jakiegoś błędu dealokacji) podczas wywoływania ExitProcess, ale nie po wywołaniu metody exit(). (związane z this question, nawiasem mówiąc).

W zasadzie chciałbym wiedzieć, w jakich okolicznościach następuje deallokacja powyższych obiektów iw jakiej kolejności (dla VC++).

Odpowiedz

14

W skrócie: Jedynym całkowicie bezpiecznym rozwiązaniem jest zezwolenie na main() lub funkcję wątku na return.

C++ standardowe gwarancje (3.6.3/1, 18,3), który destruktorów dla obiektów globalnych (w tym obiektów statycznych) zostanie wywołana jeżeli exit() nazywa, jednak wyraźnie stwierdza, że ​​destruktory dla lokalnych Zmienne nie W takim przypadku należy się z nim połączyć. exit() wywoła dowolne funkcje zarejestrowane w atexit(), a także opróżni, a następnie zamknie wszystkie otwarte strumienie stdio (w tym co najmniej stdin, stdout, stderr).

Gwarantuje, że wywołanie abort() nie wywołuje lokalnych lub globalnych destruktorów. Nie będzie też wywoływać funkcji zarejestrowanych pod numerem atexit() lub strumieni danych stdio.

Wywołanie żadnych Win32 prymitywny takie jak ExitProcess() lub ExitThread() pewno nie nazywają destruktorów dla zmiennych lokalnych, a prawie na pewno nie wywołać żadnych destruktorów dla globalnych przedmiotów ani żadnych funkcji zarejestrowanych z atexit(). Wywołanie tych funkcji bezpośrednio w programie C++ nie jest zalecane - w zasadzie te funkcje Win32 i biblioteka wykonawcza C++ nic nie wiedzą o sobie nawzajem. W rzeczywistości nawet MSDN documentation for ExitThread() radzi, aby programy C++ powracały z funkcji wątku zamiast wywoływania ExitThread().

(Teoretycznie możliwe jest, że biblioteka środowiska wykonawczego specjalnie zaaranżowała dla ExitProcess() wywoływanie globalnych destruktorów obiektów - można to zrobić, ładując określoną bibliotekę DLL, której funkcja punktu wejścia będzie wykonywać te połączenia, ponieważ ExitProcess() wywoła wpis funkcja punkt za każdy załadowany DLL z DLL_PROCESS_DETACH - ale o ile mi wiadomo, nie ma to realizacja)

+5

Właściwie ExitProcess powoduje wywołanie atexit zarejestrowanej. globalne destruktory, jeśli są zdefiniowane w DLL. Zależy to od kolejności wywołań do DLLMain (proces odrywania). Wydaje się, że ExitProcess najpierw odłączy DLL, a potem spróbuje oczyścić własne atexity, a exit() zrobi coś odwrotnego. Tak więc, jeśli zadeklarujesz statykę, która opiera się na jakiejś zewnętrznej bibliotece DLL, mogą nie ulec zniszczeniu przez ExitProcess. (Jest to oparte na niektórych eksperymentach, które dziś zrobiłem.) –

+0

Interesujące, że inne biblioteki DLL wydają się wywoływać swoje destruktory, gdy otrzymują DLL_PROCESS_DETACH.Dokumenty dla ExitProcess() nie mówią, w jakiej kolejności są wywoływane punkty wejściowe bibliotek DLL, ale nawet jeśli są one wywoływane w kolejności LIFO, myślę, że problemy mogą nadal występować, jeśli obiekty globalne w różnych bibliotekach DLL odnoszą się do siebie. –

+1

Calling dtors z DLL_PROCESS_DETACH ma sens, jeśli zauważysz, że dzwonią do ctors z biblioteki DLL_PROCESS_ATTACH. Ale to naprawdę zależy od kompilatora, który utworzył bibliotekę DLL i dzwoniącego, aby to zaaranżować. Spójrz na leniwy ładowanie DLL, aby zobaczyć inną możliwą ścieżkę implementacji. – MSalters

-3

Zobacz kod źródłowy ExitProcess() (Dodano CompuServe, usenet)

+0

Kuszono do -1 tego - jeśli to w ogóle możliwe, powinieneś unikać w zależności od szczegółów implementacji, ponieważ ** mogą ulec zmianie bez powiadomienia w dowolnym momencie ** (np. Kiedy proces Windows Update w tle instaluje aktualizację bezpieczeństwa) . To powiedziawszy, jeśli wiesz na pewno, że kod źródłowy odpowiada wersji, z której korzystasz, może to pomóc w debugowaniu czegoś. –

Powiązane problemy