Can you summarize the following document?
        
  記憶體洩漏會因為減少可用記憶體的數量從而降低計算機的效能。最終,在最糟糕的情況下,過多的可用記憶體被分配掉導致全部或部分裝置停止正常工作,或者應用程式崩潰。  記憶體洩漏帶來的後果可能是不嚴重的,有時甚至能夠被常規的手段檢測出來。在現代作業系統中,一個應用程式使用的常規記憶體在程式終止時被釋放。這表示一個短暫執行的應用程式中的記憶體洩漏不會導致嚴重後果。  在以下情況,記憶體洩漏導致較嚴重的後果:

  以下的例子無需任何程式設計的知識,但能表明如何導致記憶體洩漏及其造成的影響。請注意以下的例子是虛構的!  在此例中的應用程式是一個簡單軟體的一小部分,用來控制升降機的運作。此部分軟體當乘客在升降機內按下一樓層的按鈕時執行。  當按下按鈕時:  此程式有一處會造成記憶體洩漏:如果在升降機所在樓層按下該層的按鈕(即上述程式的第4步),程式將觸發判斷條件而結束執行,但記憶體仍一直被佔用而沒有被釋放。這種情況發生得越多,洩漏的記憶體也越多。  這個小錯誤不會造成即時影響。因為人不會經常在升降機所在樓層按下同一層的按鈕。而且在通常情況下,升降機應有足夠的記憶體以應付上百次、上千次類似的情況。不過,升降機最後仍有可能消耗完所有記憶體。這可能需要數個月或是數年,所以在簡單的測試下這個問題不會被發現。  而這個例子導致的後果會是不那麼令人愉快。至少,升降機不會再理會前往其他樓層的要求。更嚴重的是,如果程式需要記憶體去開啟升降機門,那可能有人被困升降機內,因為升降機沒有足夠的記憶體去開啟升降機門。  記憶體洩漏只會在程式執行的時間內持續。例如:關閉升降機的電源時,程式終止執行。當電源再度開啟,程式會再次執行而記憶體會重置,而這種緩慢的洩漏則會從頭開始再次發生。

  記憶體洩漏是程式設計中一項常見錯誤,特別是使用沒有內建自動垃圾回收的程式語言,如C及C++。一般情況下,記憶體洩漏發生是因為不能存取動態分配的記憶體。目前有相當數量的除錯工具用於檢測不能存取的記憶體,從而可以防止記憶體洩漏問題,如IBM Rational Purify、BoundsChecker、Valgrind、Insure++及memwatch都是為C/C++程式設計亦較受歡迎的記憶體除錯工具。垃圾回收則可以應用到任何程式語言,而C/C++也有此類函式庫。  提供自動記憶體管理的程式語言如Java、C#、VB.NET以及LISP,都不能避免記憶體洩漏。例如,程式會把專案加入至列表,但在完成時沒有移除,如同人把物件丟到一堆物品中或放到抽屜內,但後來忘記取走這件物品一樣。記憶體管理器不能判斷專案是否將再被存取,除非程式作出一些指示表明不會再被存取。  雖然記憶體管理器可以回覆不能存取的記憶體,但它不可以釋放可存取的記憶體因為仍有可能需要使用。現代的記憶體管理器因此為程式設計員提供技術來標示記憶體的可用性,以不同級別的「存取性」表示。記憶體管理器不會把需要存取可能較高的物件釋放。當物件直接和一個強引用相關或者間接和一組強引用相關表示該物件存取性較強。(強引用相對於弱引用,是防止物件被回收的一個引用。)要防止此類記憶體洩漏,開發者必須使用物件後清理引用,一般都是在不再需要時將引用設成null,如果有可能,把維持強引用的事件偵聽器全部登出。  一般來說,自動記憶體管理對開發者來講比較方便,因為他們不需要實現釋放的動作,或擔心清理記憶體的順序,而不用考慮物件是否依然被引用。對開發者來說,瞭解一個引用是否有必要保持比了解一個物件是否被引用要簡單得多。但是,自動記憶體管理不能消除所有的內容洩漏。

  如果一個程式存在記憶體洩漏並且它的記憶體使用量穩定增長,通常不會有很快的症狀。每個物理系統都有一個較大的記憶體量,如果記憶體洩漏沒有被中止(比如重啟造成洩漏的程式)的話,它遲早會造成問題。  大多數的現代計算機作業系統都有儲存在RAM晶片中主記憶體和儲存在次級儲存裝置如硬碟中的虛擬記憶體,記憶體分配是動態的——每個程序根據要求獲得相應的記憶體。存取活躍的頁面檔案被轉移到主記憶體以提高存取速度;反之,存取不活躍的頁面檔案被轉移到次級儲存裝置。當一個簡單的程序消耗大量的記憶體時,它通常佔用越來越多的主記憶體,使其他程式轉到次級儲存裝置,使系統的執行效率大大降低。甚至在有記憶體洩漏的程式終止後,其他程式需要相當長的時間才能切換到主記憶體,恢復原來的執行效率。  當系統所有的記憶體全部耗完後(包括主記憶體和虛擬記憶體,在嵌入式系統中,僅有主記憶體),所有申請記憶體的操作將失敗。這通常導致程式試圖申請記憶體來終止自己,或造成分段記憶體訪問錯誤(segmentation fault)。現在有一些專門為修復這種情況而設計的程式,常用的辦法是預留一些記憶體。值得注意的是,第一個遭遇得不到記憶體問題的程式有時候並不是有記憶體洩漏的程式。  一些多工作業系統有特殊的機制來處理記憶體耗盡得情況,如隨機終止一個程序(可能會終止一些正常的程序),或終止耗用記憶體最大的程序(很有可能是引起記憶體洩漏的程序)。另一些作業系統則有記憶體分配限制,這樣可以防止任何一個程序耗用完整個系統的記憶體。這種設計的缺點是有時候某些程序確實需要較大數量的記憶體時,如一些處理影象,視訊和科學計算的程序,作業系統需要重新配置。  如記憶體洩漏發生在核心,表示作業系統自身發生了問題。那些沒有完善的記憶體管理的計算機,如嵌入式系統,會因為一個長時間的記憶體洩漏而崩潰。  一些被公眾訪問的系統,如網路伺服器或路由器很容易被黑客攻擊,加入一段攻擊程式碼,而產生記憶體洩漏。

  值得注意的是,記憶體用量持續增加不一定表明記憶體洩漏。一些應用程式會儲存越來越多資料到記憶體中(如用作快取。如果快取太大引起問題,這可能是程式設計上的錯誤,但並非是記憶體洩漏因為資料仍被使用。另一方面,程式有可能申請不合理的大量記憶體,因為程式設計者假設記憶體總是足夠執行特定的工作;例如,影象檔案處理器會在開始時閱讀影象檔案的內容並把之儲存至記憶體中,有時候由於影象檔案太大,消耗的記憶體超過了可用的記憶體導致失敗。  另一角度講,記憶體洩漏是一種特殊的程式設計錯誤,如果沒有原始碼,根據徵兆只能猜測可能有記憶體洩漏。在這種情況下,使用術語“記憶體消耗持續增加”可能更確切。

  

  下面是一個C語言的例子,在函式f()中申請了記憶體卻沒有釋放,導致記憶體洩漏。當程式不停地重複呼叫這個有問題的函式f,申請記憶體函式malloc()最後會在程式沒有更多可用記憶體可以申請時產生錯誤(函式輸出為NULL)。但是,由於函式malloc()輸出的結果沒有加以出錯處理,因此程式會不停地嘗試申請記憶體,並且在系統有新的空閒記憶體時,被該程式佔用。注意,malloc()返回NULL的原因不一定是因為前述的沒有更多可用記憶體可以申請,也可能是邏輯地址空間耗盡,在Linux環境上測試的時候後者更容易發生。

  以下例子中,儲存了整數123的記憶體空間不能被刪除,因為地址丟失了。這些空間已無法再使用。
記憶體洩漏(Memory leak)是在電腦科學中,由於疏忽或錯誤造成程式未能釋放已經不再使用的記憶體。記憶體洩漏並非指記憶體在物理上的消失,而是應用程式分配某段記憶體後,由於設計錯誤,導致在釋放該段記憶體之前就失去了對該段記憶體的控制,從而造成了記憶體的浪費。