防止 Windows 應用程式中的記憶體流失
受影響的平臺
用戶端 - Windows 7
伺服器 - Windows Server 2008 R2
Description
記憶體流失是一種 Bug 類別,應用程式在不再需要時無法釋放記憶體。 經過一段時間後,記憶體流失會影響特定應用程式和作業系統的效能。 由於分頁過多,大型流失可能會導致無法接受的回應時間。 最後,應用程式以及作業系統的其他部分將會遇到失敗。
Windows 會在進程終止時釋放應用程式佈建的所有記憶體,因此短期執行的應用程式不會影響整體系統效能。 不過,如服務或甚至 Explorer 外掛程式等長時間執行的進程外泄,可能會大幅影響系統可靠性,而且可能會強制使用者重新開機 Windows,讓系統再次可供使用。
應用程式可以透過多個方式代表其配置記憶體。 如果使用之後未釋放,則每種配置類型都可能導致流失。 以下是常見配置模式的一些範例:
- 透過HeapAlloc 函式或其 C/C++ 執行時間對等專案 malloc或new的堆積記憶體
- 透過 VirtualAlloc 函式從作業系統直接配置。
- 核心控制碼是透過 Kernel32 API 建立的,例如 CreateFile、 CreateEvent或 CreateThread,代表應用程式保存核心記憶體
- 根據預設,透過 User32 和 Gdi32 API 建立的 GDI 和 USER 控制碼 (,每個進程都有 10,000 個控制碼的配額)
最佳做法
監視應用程式在一段時間內的資源耗用量,是偵測和診斷記憶體流失的第一個步驟。 使用 Windows 工作管理員並新增下列資料行:「認可大小」、「控制碼」、「使用者物件」和「GDI 物件」。 這可讓您建立應用程式的基準,並監視一段時間的資源使用量。
下列 Microsoft 工具提供更詳細的資訊,有助於偵測和診斷應用程式中各種配置類型的流失:
- 效能監視器和資源監視器是 Windows 7 的一部分,可監視和圖表一段時間的資源使用量
- 最新版的應用程式驗證器可以診斷 Windows 7 上的堆積流失
- UMDH 是 Windows 偵錯工具的一部分,會分析指定進程的堆積記憶體配置,並協助找出流失和其他不尋常的使用模式
- Xperf 是一種複雜的效能分析工具,可支援堆積配置追蹤
- CRT 偵錯堆積會追蹤堆積配置,並可協助建置您自己的堆積偵錯功能
某些程式碼撰寫和設計做法可以限制程式碼中的流失數目。
- 在 C++ 程式碼中使用智慧型指標來進行堆積配置,以及用於 Win32 資源,例如核心 HANDLE。 C++ 標準程式庫提供堆積配置的 auto_ptr 類別。 針對其他配置類型,您必須撰寫自己的類別。 ATL 程式庫提供一組豐富的類別,可用於堆積物件和核心控制碼的自動資源管理
- 使用 _com_ptr_t 之類的編譯器內建功能,將您的 COM 介面指標封裝成「智慧型指標」,並協助參考計數。 其他 COM 資料類型有類似的類別: _bstr_t 和 _variant_t
- 監視 .NET 程式碼不尋常的記憶體使用量。 Managed 程式碼對記憶體流失並無影響。 請參閱如何找出 GC 流失的「追蹤受控記憶體流失」
- 請注意 Web 用戶端程式代碼中的外泄模式。 COM 物件與 JScript 等腳本引擎之間的迴圈參考可能會導致 Web 應用程式中發生大量流失。 「瞭解及解決 Internet Explorer 流失模式」 有這些類型外泄的詳細資訊。 您可以使用 JavaScript 記憶體流失偵測器,對程式碼中的記憶體流失進行偵錯。 雖然 Windows Internet Explorer 8 隨附于 Windows 7,但可減輕這些問題的大部分問題,舊版瀏覽器仍然容易受到這些 Bug 的影響
- 避免從函式使用多個結束路徑。 指派給函式範圍變數的配置應該在函式結尾的一個特定區塊中釋放
- 請勿在程式碼中使用例外狀況,而不釋放函式中的所有區域變數。 如果您使用原生例外狀況,請在 __finally 區塊內釋放所有配置。 如果您使用 C++ 例外狀況,所有堆積和處理配置都必須包裝在智慧型指標中
- 請勿捨棄或重新初始化 PROPVARIANT 物件,而不呼叫 PropVariantClear 函式
資源的連結
常見的配置模式:
Microsoft 工具:
其他連結:
- auto_ptr 類別
- 使用中範本程式庫 (ATL) 記憶體類別
- _com_ptr_t 物件
- _bstr_t 類別
- _variant_yt 類別
- 「追蹤受控記憶體流失」
- 「瞭解及解決 Internet Explorer 流失模式」
- 「JavaScript 記憶體流失偵測器」
- 瀏覽器中的迴圈記憶體流失風險降低 () :
- try-finally 陳述式
- PROPVARIANT 結構
- PropVariantClear 函式