Was passiert beim Schließen eines Programms?



  • Hallo,

    ich würde gerne wissen, was passiert, wenn man ein Programm über das X schließt. Liege ich damit richtig, das alle OnExit Funktionen sowie alle Destruktoren aller Klassen ausgeführt werden?
    Wenn ich die exit() Funktion benutze, wird das Programm doch ohne Aufruf der OnExit und Destruktoren beendet. Wie beende ich denn dann am besten ein GUI-Programm, wenn ich gerade im Code einer Buttonfunktion bin? Bei einem return werden ja nur die Operationen der Buttonfunktion abgebrochen.

    Mit freundlichen Grüßen,
    DarkBug



  • DarkBug schrieb:

    Wie beende ich denn dann am besten ein GUI-Programm, wenn ich gerade im Code einer Buttonfunktion bin?

    Du sagst dem Windows "Bitte schick mir bald eine Nachricht, die mich veranlaßt, mich zu schließen."
    Wie das genau abgeht, hängt vom Framework ab. Pure Winapi wäre http://msdn.microsoft.com/en-us/library/ms644945(VS.85).aspx und dann bei der in Kürze kommenden WM_QUIT macht die Hauptschleife ihr return.



  • Danke für die Antwort. Also die OnClose Funktion wird bei Aufruf der PostQuitMessage Funktion nicht mehr aufgerufen. Die exit Funktion hingegen ruft die OnClose Funktion noch auf. Bist du dir sicher, das die Funktion die Destruktoren der Klassen noch aufruft?

    Mit freundlichen Grüßen,
    DarkBug



  • Von http://msdn.microsoft.com/en-us/library/6wdz5232(v=VS.80).aspx:

    When you call the exit or _exit functions, the destructors for any temporary or automatic objects that exist at the time of the call are not called. An automatic object is an object that is defined in a function where the object is not declared to be static. A temporary object is an object created by the compiler.

    Wenn ich mich nicht irre heißt das, dass von sämtlichen globalen, statischen und mit new erzeugten Objekten der Destruktor aufgerufen wird. Nicht aber bei lokalen Objekten, die noch auf dem Stack liegen, oder ebend die erwähnten temporären Objekte die der Compiler erzeugt.



  • Das ist vollkommen egal. So bald der Prozess terminiert, wird von Windows auch der Adressraum aufgeräumt und frei gegeben. Da bleibt nichts mehr im Speicher. Bei DLLs muss man allerdings aufpassen, da ist es etwas komplexer.



  • _Luckie schrieb:

    Das ist vollkommen egal. So bald der Prozess terminiert, wird von Windows auch der Adressraum aufgeräumt und frei gegeben. Da bleibt nichts mehr im Speicher. Bei DLLs muss man allerdings aufpassen, da ist es etwas komplexer.

    Nur den Speicher zu sehen, ist sowas von Java. Halboffene Transaktionen, temporäre Dateien, unvollständige Logs, Locks, ...



  • Ich habe mich auf die Frage bezogen. Offene Handles werden übrigens auch geschlossen. Und wenn temporäre Dateien übrig bleiben, dann ist das Schuld des Programmierers.



  • "Offene Handles werden übrigens auch geschlossen"
    GDI-Handles ??



  • Man sollte allerdings als Reaktion auf einen Schließen-Button nicht direkt PostQuitMessage aufrufen, denn sonst hat das Programm keine Chance mehr eventuelle Ressourcen freizugeben. Besser ist ein

    PostMessage(hwnd, WM_CLOSE, 0, 0);
    

    (wird ja normalerweise auch gemacht wenn ihr das Fenster über das X schließt)



  • Chew-Z schrieb:

    "Offene Handles werden übrigens auch geschlossen"
    GDI-Handles ??

    GDI Handles werden in einer Systemweiten Tabelle abgelegt, zusammen mit dem Process-Identifier des erzeugenden Prozesses. Damit ist es für das System ein Leichtes, die erzeugten GDI-Handles nach Beendigung des Prozesses automatisch freizugeben. Und genau das passiert auch.



  • @_Luckie: Soll das nun heißen, das man Funktionen wie CloseHandle, WSACleanup oder delete gar nicht verwenden brauch, weil Windows das alles für einen macht, wenn das Programm beendet wird?

    @All: Also würde das Handle ohne CloseHandle nach der PostMessage noch von Windows geschlossen werden?

    HANDLE Form1;
    Form1 = FindWindow(NULL,"Form1");
    PostMessage(Form1, WM_CLOSE, 0, 0);
    

    Werden danach denn nun noch Destruktoren ausgeführt? Wie sieht es denn nun mit exit aus, ist es genauso sicher wie PostMessage? Welche Funktion benutzt ihr?

    Mit freundlichen Grüßen,
    DarkBug



  • Wenn Du eine Fremdanwendung schließen willst:
    How To Terminate an Application "Cleanly" in Win32

    Bei einer eigenen Anwendung hat man ja meistens sowas:

    LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        switch(uMsg)
        {
             case WM_CLOSE:
                 // User hat aufs 'X' geklickt, auf 'Task beenden' im Taskmanager, etc...
                DestroyWindow(hwnd);
                break;
             case WM_DESTROY:
                PostQuitMessage(hwnd,0);
                break;
             default:
                return DefWindowProc(hwnd,uMsg,wParam,lParam);
         }
         return 0;
    }
    

    D.h. man würde WM_CLOSE ans eigene Fenster senden, das würde verursachen dass das Fenster zerstört wird und eine WM_DESTROY ankommt.
    WM_DESTROY wieder würde PostQuitMessage() aufrufen, welches eine WM_QUIT-Nachricht erzeugt, die dafür sorgt dass die MessageLoop stoppt und hinter der MessageLoop ist meistens kein Code mehr und das Programm ist zu Ende und Windows fängt an vergessene Reste (Handles, etc.) aufzuräumen...


  • Mod

    _Luckie schrieb:

    Das ist vollkommen egal. So bald der Prozess terminiert, wird von Windows auch der Adressraum aufgeräumt und frei gegeben. Da bleibt nichts mehr im Speicher. Bei DLLs muss man allerdings aufpassen, da ist es etwas komplexer.

    Aber nicht alle Ressourcen werden bei einem Prozessende aufgelöst.
    Es bleiben gerne Leichen bei den Dateisperren. Semaphoren und Mutexe könnnen auch evtl. weiterhin gesperrt bleiben.

    Sollte also solch eine Ressource erst aufgerämt werden wenn das Fenster sein WM_(NC)DESTROY bekommt (was ich gerne mache), dann sind slche Systemlecks vorprogrammiert.

    Siehe auch:
    http://blog.m-ri.de/index.php/2007/12/09/die-unsitte-postquitmessage-zum-beenden-eines-programmes-zu-verwenden/



  • Beispiel:
    Es gibt zwei Fenster und das zweite Fenster wird geschlossen, sobald das erste Fenster geschlossen wird.

    Form1 = Fenster 1
    Form2 = Fenster 2

    Folgender Code müsste also der richtige Weg sein das Programm zu beenden:

    HANDLE Form1;
    Form1 = FindWindow(NULL,"Form1");
    DestroyWindow(Form1);
    PostQuitMessage(0);
    

    So beendet Windows aber auf jeden fall nicht das Programm, denn OnClose-Funktionen werden ignoriert, im Gegensatz zu folgendem Code:

    HANDLE Form1;
    Form1 = FindWindow(NULL,"Form1");
    PostMessage(Form1, WM_CLOSE, 0, 0);
    

    1. Wie beendet Windows das Programm, wenn man auf das X klickt?

    2. Ist es eigentlich nicht möglich einfacher das Handle des momentanen Fensters zu bekommen?

    3. Folgender Post wurde noch gar nicht beantwortet:

    DarkBug schrieb:

    @_Luckie: Soll das nun heißen, das man Funktionen wie CloseHandle, WSACleanup oder delete gar nicht verwenden brauch, weil Windows das alles für einen macht, wenn das Programm beendet wird?

    @All: Also würde das Handle ohne CloseHandle nach der PostMessage noch von Windows geschlossen werden?

    HANDLE Form1;
    Form1 = FindWindow(NULL,"Form1");
    PostMessage(Form1, WM_CLOSE, 0, 0);
    

    Werden danach denn nun noch Destruktoren ausgeführt? Wie sieht es denn nun mit exit aus, ist es genauso sicher wie PostMessage? Welche Funktion benutzt ihr?

    Mit freundlichen Grüßen,
    DarkBug

    Mit freundlichen Grüßen,
    DarkBug


  • Mod

    Chew-Z schrieb:

    "Offene Handles werden übrigens auch geschlossen"
    GDI-Handles ??

    Prozessweite gesperrte Mutexe bzw. Semaphoren bilden hier aber leider eine Aussnahme! Deshalb sollte eine Anwendung immer "sauber" beendet werden.



  • Aber warum soll man zunächst DestroyWindow() aufrufen? Was macht DestroyWindow(), was ein Beenden ohne dem nicht macht?


  • Mod

    WieJetzt schrieb:

    Aber warum soll man zunächst DestroyWindow() aufrufen? Was macht DestroyWindow(), was ein Beenden ohne dem nicht macht?

    DestroyWindow löst ja auch etwas aus? Oder?

    Wenn die Nachricht WM_DESTROY in enem Fenster ankommt, dann hat das Fenster selber die Möglichkeit darauf zu reagieren. Anschließend wird in vielen Fameworks auch noch der Destruktor des Windows Objektes aufgerufen, der auch noch aufräumt (insbesondere evtl. Mutexe oder Semaphoren freigibt für IPC etc., evtl. Pipes Schließt oder auch korrekt abschließt).

    Klar auf der puren Prozessebene kann man enfach das Programm verlassen und abschießen. Das Windows OS ist an dieser Selle ziemlich robust, aber nicht unfehlbar!
    Aber dieses Vorgehen schließt eben Leaks auf anderer Seite nicht aus, weil man eben nicht weiß wie intern die Entwickler es machen, dass die Ressourcen wieder freigeben werden...



  • Könntet ihr bitte meine Fragen beantworten.

    DarkBug schrieb:

    Beispiel:
    Es gibt zwei Fenster und das zweite Fenster wird geschlossen, sobald das erste Fenster geschlossen wird.

    Form1 = Fenster 1
    Form2 = Fenster 2

    Folgender Code müsste also der richtige Weg sein das Programm zu beenden:

    HANDLE Form1;
    Form1 = FindWindow(NULL,"Form1");
    DestroyWindow(Form1);
    PostQuitMessage(0);
    

    So beendet Windows aber auf jeden fall nicht das Programm, denn OnClose-Funktionen werden ignoriert, im Gegensatz zu folgendem Code:

    HANDLE Form1;
    Form1 = FindWindow(NULL,"Form1");
    PostMessage(Form1, WM_CLOSE, 0, 0);
    

    1. Wie beendet Windows das Programm, wenn man auf das X klickt?

    2. Ist es eigentlich nicht möglich einfacher das Handle des momentanen Fensters zu bekommen?

    3. Folgender Post wurde noch gar nicht beantwortet:

    DarkBug schrieb:

    @_Luckie: Soll das nun heißen, das man Funktionen wie CloseHandle, WSACleanup oder delete gar nicht verwenden brauch, weil Windows das alles für einen macht, wenn das Programm beendet wird?

    @All: Also würde das Handle ohne CloseHandle nach der PostMessage noch von Windows geschlossen werden?

    HANDLE Form1;
    Form1 = FindWindow(NULL,"Form1");
    PostMessage(Form1, WM_CLOSE, 0, 0);
    

    Werden danach denn nun noch Destruktoren ausgeführt? Wie sieht es denn nun mit exit aus, ist es genauso sicher wie PostMessage? Welche Funktion benutzt ihr?

    Mit freundlichen Grüßen,
    DarkBug

    Mit freundlichen Grüßen,
    DarkBug


Anmelden zum Antworten