Immer wieder lese ich Postings in http://www.c-plusplus.de/forum die es anpreisen ein Programm mit PostQuitMessage zu beenden, genau so unsinnig wie WM_QUIT zu versenden.
Das ist natürlich Unfug! Sicherlich wird ein Programm durch PostQuitMessage beendet, aber warum?
Weil die Nachrichtenschleife verlassen wird und letzten Endes WinMain verlassen wird. Dies führt dazu, dass die darunter liegenden CRT Routinen irgendwann ExitProcess ausführen. BTW: Würde hier nur ein der CRT einfacher return erfolgen, dann würde der Prozess weiterleben, wenn noch ein einziger anderer Thread aktiv wäre.
Das brutale Verlassen führt aber letzten Endes auch dazu, dass erst ExitProcess brutal alle Fenster aufräumt. D.h. kein Fenster wird normal zerstört, kein WM_DESTROY bzw. WM_NCDESTROY wird empfangen. D.h. alle normalen Prozesse, die dem Aufräumen und Freigeben von Ressourcen dienen, werden außer Kraft gesetzt.
Ja und sicherlich gibt ExitProcess Speicher frei, die der Prozess alloziert hat, auch einige Handles können freigegeben werden, aber nicht alle (z.B. benamte Mutexe und Semaphoren).
Bei einem Mikey Mouse Win32 API Programm mag dies kein Problem sein, denn hier gibt es keine Ressourcen, die Prozessübergreifend ein Leak verursachen würden, oder eine Ressource blockieren würden.
Aber grundsätzlich würde ich es unterlassen. Jede andere Library, die man verwendet, jedes externe Control, dass man einbindet könnte genau auf dieses entscheiden WM_DESTROY angewiesen sein um Ressourcen freizugeben, die ein System blockieren könnten. Solange man nicht 100%ig weiß wie die benutzen Bibliotheken arbeiten, ja nicht einmal detailliert weiß wie COM und die CRT Handles behandeln würde ich grundsätzlich abraten ein Programm einfach mit ExitProcess zu verlassen, genau so wie ich abrate TerminateProcess zu verwenden.
Der richtige Weg ist und bleibt es das/alle Main Window(s) zu zerstören und entsprechend dann (im WM_DESTROY Handler) PostQuitMessage (AfxPostQuitMessage) auszuführen. Durch das Zerstören des Hauptfensters werden natürlich alle enthaltenen Child-Windows mit zerstört. Alle Fenster bekommen damit die Chance hinter sich aufzuräumen und Ressourcen frei zu geben.
PS: Aber solche Unsitten lassen sich kaum ausmerzen. Genauso wenig wie die Unsitte einen HINSTANCE Wert einfach durch Aufruf von GetModuleHandle(NULL) zu bestimmen… Auch eine Unsitte, die wohl niemand mehr ausmerzen wird.
Damit bekommst Du diesen Monat den Don-Quichotte-Preis in Form einer goldenen Windmühle. Obwohl, wenn wir Du noch ein paar dieser Unsitten sammeln könntest, brauchst Du nur noch einen guten Verleger. Ich sehe schon den Titel: „Die sieben Todsünden der C++ Programmierung…“ und wenn Du länger drüber nachdenkst, ist da mehr dran, als man es vielleicht auf den ersten Blick vermuten mag.
Jooo. Wenn es schon nicht mit dem 43Mio Jakpot geworden ist, dann doch wenigstens ein solcher „Windmühlen-Preis“!
Im PS habe ich ja die nächste „Sünde“ schon angesprochen. Mal sehen ob ich auf 7/9 Todsünden komme.
BTW: Nach anderer Zählung gibt es übrigens 9 Todsünden!
Hochmut, Geiz, Neid, Zorn, Wolllust, Völlerei, Trägheit (die klassischen 7) dazu kommen Lüge, Furcht.
Ach, da finden sich noch Hunderte, behaupte ich mal. Nimm zum beispiel nur die Unsitte, Kontextmenues an WM_RBUTTONDOWN statt an WM_CONTEXTMENU zu binden. Oder Keyboardhandling allgemein. Aber egal, ich muss mich ja nimmer aufregen.
Und zu den Todsünden. Als jemand der zu Völlerei neigt, sollte ich mich nicht zu weit aus dem CWnd lehnen, aber während ich „Lüge“ ja noch akzeptieren kann, bin ich mir sicher, dass viele gegen ihre Furcht einfach nicht ankommen. Insofern würde ich dann niemandem einen Vorwurf machen wollen.
Viel peinlicher finde ich persoenlich den umgekehrten Fall:
Wenn im Zweig WM_DESTROY der (Haupt-)Fensterprozedur der
PostQuitMessage(0) vergessen wird. Dann geht das (Haupt-)Fenster
zu, es ist nix mehr zu sehen, der unbedarfte User denkt: Beendet,
aber in der Prozessliste sieht man den immer noch laufenden Prozess,
was der unbedarfte User aber nicht sieht und deshalb einen neuen
Start dieses Programmes versucht….
Moin, um ehrlich zu sein ich bin neu, aber für mich ergibt, nach Recherche auf der MSDN Seite zur PostQuitMessage, das allgemeine enorme Aufregen keinen Sinn.
Kurz neben dem Thema muss ich sagen, dass ich mich ein bisschen verarscht fühle, weil ich irgendwie versuche mir das Wissen über DirectX 11 und die WinAPI zusammenzukratzen. Ich finde nämlich absolut nirgends gute Hilfen in dieser Richtung. Und dann lese ich so ein Thread… wirft kein gutes Licht auf „Programmierer“.
Zum Thema: Ich benutze PostQuitMessage, um die Message Loop zu verlassen. Dabei wird lediglich die WM_QUIT message auf die Message-Queue gelegt und somit die Loop beendet. Dann wird direkt eine Methode aufgerufen zum Bereinigen des Speichers (COM interfaces, andere pointer etc.).
„Indicates to the system that a thread has made a request to terminate (quit).“ – MSDN
Das klingt für mich nicht im geringsten nach „brutalem Verlassen“
Zudem empfielt Microsoft es sogar.
So gebt mir doch bitte einen Grund auf Microsoft zu scheißen und statt dessen auf einen von euch zu hören.
Freundliche Grüße
Das kannst Du sehen wie Du möchtest.
1. Wenn Du nicht mehr als ein Fenster hast, dann ist das ziemlich egal.
2. Das Problem ist wenn Dein Hauptfenster eine Kaskade/Baum von Unterfenstern erzeugt. Verlässt Du einfach die Messageloop, dann wird eben nicht aufgeräumt. Das Risiko Ressourcen nicht freizugeben ist extrem hoch.
3. Wenn Du PostQuitMessage ausgelöst hast, hat Dein Programm keine Chance mehr einen Fehler zu melden.
4. „Indicates“ bedeutet, dass Du die Verantwortung hast! Du musst aufräumen, aber darüber diskutiert ja keiner in den 1000 „schrottigen“ Tipps im Netz.
5. Wo empfiehlt das Microsoft? Die MSDN Doku steht dagegen,… würde ich sagen.
Letzten Endes musst Du das selbst verantworten. Ich bleibe dabei, es ist eine Unsitte!
Just my to cents.