1. 程式人生 > >SendMessage和 PostMessage; 使用PostMessage(WM_QUIT)退出程式時導致的記憶體洩漏問題

SendMessage和 PostMessage; 使用PostMessage(WM_QUIT)退出程式時導致的記憶體洩漏問題

引言:我們要使用程式碼關閉程式的話,應該向視窗傳送WM_CLOSE或者直接調DestroyWindow(HWND)函式   (預設情況下WM_CLOSE的訊息響應就是呼叫DestroyWindow(HWND)   函式,所以我們直接呼叫也達到一樣的效果).這樣可以令作業系統回收窗口占用著的記憶體資源後再退出程式.

千萬不要直接用PostMessage(WM_QUIT);令程式退出,這樣程式是可以退出了,但是窗口占用的記憶體資源就沒辦法回收,久而久之程式就執行出錯了.

-------------------------------------------------------------------------------------------------------

使用PostMessage(WM_QUIT)退出程式時導致的記憶體洩漏

先看一下MSDN的介紹:

The SendMessage function sends the specified message to a window or windows. It calls the window procedure for the specified window and does not return until the window procedure has processed the message.

The PostMessage function places (posts) a message in the message queue associated with the thread that created the specified window and returns without waiting for the thread to process the message.

 從MSDN的解釋上看,感覺SendMessage比PostMessage更加安全,因為,SendMessage要等到窗體訊息處理完才返回,而PostMessage傳送訊息後就立即返回,這更令人茫然。既然從這上面看不出SendMessage無法實現的原因,那麼就從訊息WM_QUIT上查。

The WM_QUIT message indicates a request to terminate an application and is generated when the application calls the PostQuitMessage function. It causes the GetMessage

 function to return zero.

    當應用程式呼叫PostQuitMessage函式的時候, WM_QUIT訊息終止一個程式的,它促使GetMessage函式返回0。

    可這裡根本就沒提SendMessage無法完成終止程式的原因。但在Remark中,卻有這樣一句:

Do not post the WM_QUIT message using the PostMessage function; use PostQuitMessage。至於為什麼,就得看PostQuitMessage做什麼事了。現在不討論為什麼不讓使用PostMessage傳送WM_QUIT訊息,但就為什麼SendMessage無法完成PostMessage能完成的功能來做一下研究。

注意到WM_QUIT訊息讓訊息迴圈終止歸根結底是讓GetMessage返回為0,而GetMessage函式是從訊息對列裡取一條訊息,然後再返回,只能當訊息為WM_QUIT時才返回0結束訊息迴圈。再仔細看一下SendMessage的註釋發現,SendMessage直接傳送到視窗,並呼叫視窗處理程式,完成訊息響應,即SendMessage 根本就沒有將訊息發到訊息對列中,因此GetMessage無法從訊息對列中收到WM_QUIT的訊息。而PostMessage卻直接傳送訊息到訊息對列中,然後立即返回,這一點點的區別就解決了我們上面的問題。

    瞭解了這一點,就不難理解上面註釋中說的為什麼不讓直接使用PostMessage來發送WM_QUIT訊息來終止程式了。

    另外需要注意的是,傳送訊息讓對話方塊關閉,應該傳送WM_CLOSE或者直接呼叫)訊息,這樣可以讓對話方塊完成它自身的資源釋放回收。