簡體   English   中英

Stack Unwinding問題上的Java和C ++

[英]Java and C++ on Stack Unwinding issue

據我所知,在未捕獲異常的情況下,C ++會立即銷毀局部變量,Java會釋放引用並將其余部分留給垃圾收集器。

這是正確的嗎? Java和C ++在這個問題上究竟有什么區別? 換句話說,就堆棧展開問題而言,這兩種語言中的哪一種被認為更好? :)

我會為此受到抨擊,但......

在堆棧展開前,C ++比Java更好 - 沒有競爭。 C ++對象析構函數一直觸發堆棧直到達到捕獲點 - 沿途釋放所有托管資源。

正如你所說的那樣,Java將所有這些都置於非確定性垃圾收集器(最壞的情況)或者任何明確制作的最終塊的手中,你已經散布了你的代碼(因為Java不支持真正的RAII) 。 也就是說,所有資源管理代碼都掌握在每個類的客戶手中,而不是應該在類設計者手中。

也就是說,在C ++中,如果您小心確保析構函數本身不會發出異常,則堆棧展開機制只能正常運行。 一旦你有兩個活動的例外,你的程序abort()沒有通過go(當然也沒有觸發任何剩余的析構函數)。

堆棧展開專門調用調用鏈上的所有完全構造的對象的析構函數,直到捕獲到異常的點。

Java根本沒有堆棧展開 - 如果拋出異常,它對對象不做任何事情。 你必須自己處理catchfinally塊中的對象。 這主要是為什么C#引入了using語句 - 它們簡化了調用IDisposable.Dispose(),但同樣不是C ++堆棧展開的完全替代。

你是完全正確的,C ++以相反的順序銷毀所有局部變量,因為它退出堆棧上的每個函數 - 就像你以編程方式執行return - 而不是main()

對於堆棧,請執行相同的操作:它們釋放您離開的塊的堆棧,但異常。 在Java中,所有原始類型(int,double等)都直接保存,此時此類型的局部變量被釋放。 所有對象都通過局部變量中的引用保存,因此引用將被刪除,但對象本身仍保留在堆上。 如果這是對象的最后一個引用,它們將在下一個垃圾回收中釋放。 如果在C ++中是在堆上創建的對象並且局部變量保留指針,則堆上的對象不會自動釋放,它們永遠保留在堆上(是的,你得到一個MEMORY LEAK)。 如果已在堆棧上保存了對象,則會調用析構函數(並且可能會釋放堆上的其他引用對象)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM