2010-08-25 56 views
5

一般規則,只有在免費商店中分配的對象可能導致內存泄漏。 但是在堆棧中創建的對象沒有。這是否被認爲是內存泄漏?

這裏是我的疑問,

int main() 
    { 
     myclass x; 

     ... 

     throw; 

     ... 
    } 

如果拋不處理,它調用,終止(),這反過來又調用abort()和崩潰的應用程序。此時,堆棧中的對象不會被刪除(析構函數未被調用)。

我的理解是「當應用程序終止時(通過中止或正常退出),它釋放爲應用程序分配的所有內存」。因此這不能被視爲內存泄漏。

我正確嗎?

+0

我們應該假設一個單線程應用程序? – 2010-08-25 21:01:38

+3

讓我們清楚一點,'throw;'在你的代碼中相當於'terminate()',因爲你試圖重新拋出一個沒有重新拋出的異常。無論是否展開堆棧,它都是實現定義的。如果你拋出* something *,所有自動變量都必須調用它的析構函數。這就是SBRM(RAII)背後的全部想法。 – GManNickG 2010-08-25 21:03:45

+0

jdv,是的,它是一個單線程應用程序。 – user373215 2010-08-25 21:10:09

回答

5

在應用程序終止所佔用的所有內存時,操作系統會自動回收宿主環境(例如,典型的Unix/Windows/Mac OS X,甚至DOS,計算機)。因此,擔心這種內存泄漏是沒有意義的。

在某些情況下,在應用程序終止之前,您可能想要釋放您分配的所有動態內存,以便通過泄漏檢測器檢測潛在的內存泄漏,如valgrind。但是,即使在這種情況下,您所描述的示例也不會被視爲內存泄漏。

一般來說,未能調用析構函數與導致內存泄漏不同。內存泄漏源於堆中分配的內存(使用new或malloc或容器分配器)。堆棧分配的內存在堆棧解放時自動回收。但是,如果一個對象擁有一些其他資源(比如文件或窗口句柄),調用它的析構函數將會調用資源泄漏,這也可能是一個問題。同樣,現代操作系統在應用程序終止時將回收它們的資源。

+0

優秀的解釋。謝謝。 – user373215 2010-08-25 21:09:24

+0

可靠的解釋,但正如丹尼斯指出的那樣 - 一些資源可能不會自動回收:例如共享內存段,其中的鎖,應用程序的文件。通常會刪除。 – 2010-08-26 06:36:16

2

答案是,它取決於操作系統。我無法想象現代操作系統不這樣做。但是如果程序在不釋放其內存請求的情況下關閉,那麼舊的系統(我認爲最好在Windows中贏得3.1,以及一些舊的嵌入式Linux平臺),操作系統會保留它們直到重新啓動。

4

編輯:正如GMan所說的那樣,「扔」;重新拋出以前拋出的異常,或者如果沒有,立即終止。由於在這種情況下沒有,因此立即終止。

終止一個進程總是會清理任何現代操作系統中任何剩餘的用戶態內存,所以通常不被視爲「內存泄漏」,它被定義爲在運行進程中未釋放的未引用內存。但是,真正由操作系統來決定這樣的事情是否被認爲是「內存泄漏」。

+0

在這種情況下是否調用析構函數是實現定義的,但是您做出保證。 (它不會拋出任何異常。) – GManNickG 2010-08-25 21:07:11

+0

在我的情況下,析構函數沒有被調用。因此,我發佈了這個問題。 – user373215 2010-08-25 21:08:26

+0

GMan是正確的...因爲在這種情況下「拋出」不會拋出任何異常。 「扔;」獨自重新拋出以前拋出的異常,這是你沒有的。由於沒有以前拋出的異常,它會立即終止。 因此,無論是「內存泄漏」是由您正在運行的操作系統定義。目前沒有我知道的操作系統不會清理已終止進程的內存,但是在這種情況下由操作系統來防止內存泄漏。 – samkass 2010-08-25 21:25:53

1

內存泄漏被認爲是一個問題,因爲長時間運行的應用程序會慢慢流失系統內存,最壞的情況可能會導致整個機器由於內存不足而無法使用。在你的情況下,應用程序終止,並且分配給應用程序的所有內存將被返回給系統,所以幾乎沒有問題。

+0

謝謝Deus。好答案。 – user373215 2010-08-25 21:10:52

1

真正的問題是,「myclass是否分配任何必須被釋放/刪除的內存?」

如果沒有 - 如果它使用的唯一內存是內部成員 - 那麼它完全存在於堆棧上。一旦它離開該功能(但是它),堆棧中的內存將被回收並重新使用。 myclass不見了。這只是堆棧工作的方式。

如果MyClass的不分配內存,需要在它的析構函數被釋放,那麼你仍然在運氣,因爲作爲堆棧扔期間展開的析構函數將被調用。在異常被聲明爲未處理並且終止被調用之前,dtor已經被調用。

你將有一個問題的唯一地方是,如果MyClass的有析構函數,和析構函數拋出異常作爲它自己。在第一次擲出的堆棧中發生的第二次拋出將會使得它在沒有任何更多調用者被調用的情況下立即調用終止。

0

我的理解是「當應用程序終止(通過中止或正常退出),它釋放爲應用程序分配的所有內存」。因此這不能被視爲內存泄漏。

我正確嗎?

內存泄漏是一種編程錯誤,與未捕獲的異常相比,在編程錯誤的規模上排名稍低。

督察,如果程序不正確地終止,又名崩潰,那麼現在還太早談論內存泄漏。

在其他的說明,我已經有超過過去十年的工作最內存分析器不會觸發的情況下,任何內存泄漏報警器 - 因爲他們不會觸發任何警報的時候程序崩潰默默。首先必須讓程序不崩潰,然後調試內存泄漏。

1

從OP,

如果拋不處理,它調用, 終止(),這反過來又調用 中止()和崩潰的應用程序。 此時,在堆棧 的對象不destoryed(析構函數 不調用)。

這是一個實現定義的行爲。

$ 15.3/9-「如果程序沒有找到匹配的處理器 ,功能 終止()被調用,這個調用 之前的協議棧是否 被解開終止()是 實施(15.5.1)「。

因此,不管這是否構成內存泄漏也是實現定義的行爲,我猜。

+0

謝謝Chubsdad。這是一個很好的解釋。 – user373215 2010-08-26 09:46:51