2010-09-09 64 views
4

因此,我已經知道目標C中的內存管理,而我在使用.net(C#)進行編程時從來不需要了解它。但是我仍然對一切如何完成有一些疑問。內存管理 - C#VS Objective C?

- 爲什麼如果我們分配一個對象而不釋放它,爲什麼代碼在目標c中泄漏?

- 爲什麼不在C#中泄漏?

- 自動垃圾收集的一些優點和缺點是什麼?

- 爲什麼不在每個分配的對象上使用autorelease(Objective C)?

- 是否可以手動處理內存(C#)?所以我們假設我實例化一個對象,並且當我完成時我想要釋放它,並且我不想等垃圾收集器來做它?

+1

嗯,似乎我與一羣iPhone開發者競爭,他們不知道Objective-C 2.0在Mac上有垃圾收集。 http://en.wikipedia.org/wiki/Objective-C#Garbage_collection – Justin 2010-09-09 03:27:06

+0

:)不,我認爲他們有更高的票數,因爲他們回答了1的問題:)。但是知道mac上的目標c有垃圾收集器 – aryaxt 2010-09-09 03:40:43

回答

8
  • 它泄漏在Objective-C,因爲Objective-C的不採取任何行動。它依靠你做所有的工作。它不會在C#中泄漏(更確切地說,在.NET中),因爲它使用了一個垃圾回收器,它清理不再使用的對象。

  • 垃圾回收的主要優勢在於:內存泄漏少得多。 (仍然有可能發生內存泄漏,例如通過無限期地填充列表,但這很偶然。)過去人們認爲垃圾收集存在一個缺點,因爲它可能會減慢程序的運行速度,因爲它會一直在後臺執行垃圾收集,而且您幾乎無法控制它。但實際上,這種差異可以忽略不計:您的計算機上還有其他後臺任務(例如設備驅動程序)一直在運行,垃圾收集器也不會破壞駝背。

  • 自動釋放(因爲在非指針變量超出作用域時在C++中使用)是危險的,因爲即使在對象已被釋放後,它仍然存在引用該引用的可能性。如果你的代碼試圖訪問這個對象,那麼這個過程會花費大量的時間。

  • 是的,可以通過直接調用垃圾回收器來告訴C#釋放內存(GC.Collect())。但是,我還沒有看到這種情況是必要的。如果實際內存不足,垃圾收集器將會盡可能地自動釋放並釋放內存。

+0

你可以告訴垃圾收集器運行,但它只會收集它「應該」的東西 - 如果仍然有對它的引用,它就不會釋放你的對象,也不應該。但GC.Collect()只是一個提示。它告訴垃圾收集者現在集合是可行的,因爲我們可以處理滯後,但如果它不認爲有太多工作要做,它可能會忽略你。 – 2010-09-09 02:50:11

+1

Mac上的Objective-C也有一個垃圾收集器(此時不在iPhone上)。 – Justin 2010-09-09 06:34:39

4

自動垃圾回收的優點是,您不必像所說的那樣顯式釋放/釋放對象。缺點是你不能確定什麼時候(或者甚至)是否會釋放任何給定的對象實例。

C#有其他機制來釋放其他資源,例如文件或數據庫連接,這些資源必須直接釋放。例如,using可以確保在對象上調用IDispose。

垃圾收集系統在任何給定的時間都傾向於使用更多的內存,而不是調整好的手動實現。當然,你沒有內存泄漏。

垃圾收集器的質量和性能可能會有很大的不同,這是你可能沒有太多的控制權。例如,GC運行時可能會有明顯的滯後。在.NET中,您可以致電GC.Collect()告訴GC現在是個好時機,但它可能會聽,也可能聽不到。

這幾天Objective-C也是垃圾收集在Mac上。在iPhone上,它是引用計數,儘管如此,我認爲這是你遇到問題的地方。

在垃圾收集系統上,您仍然可能遇到掛起對象的引用的問題,該對象將引起垃圾回收。垃圾收集器不會清理它,所以內存本質上是泄漏的。

在參考計數系統中,您不必跟蹤指向您的對象實例的每個對象,但您必須指定您希望它們發佈。

編輯:我想我沒有明確地說 - 你不能手動控制在C#中的內存分配。

+0

從ac#的角度來看,非常有意思的是,自動垃圾收集也帶有內存和速度懲罰 - 因爲系統必須跟蹤堆中的所有變量,所有對他們的引用。另外,當自動垃圾收集器運行時不能被預測(雖然可以調用它),所以你可以發現編寫不好的時序代碼會受到垃圾收集器操作的不利影響。 – 2010-09-09 02:54:54

+0

@Tim - 我的回答已經提到GC有內存影響,我談到了GC實現的不同性能。我應該在我的答案中添加其他內容嗎? – Justin 2010-09-09 03:29:37

5

的Objective-C是不是一個垃圾收集語言,因此它無法知道一個對象將不再除非你告訴它使用的方式。這就是.NET垃圾收集器的目的:它檢查程序中不再使用哪些對象,並且 - 在某些時候 - 擺脫它們以釋放內存。對於什麼時候或是否會釋放任何被遺棄的物體沒有保證;它只是試圖防止內存使用失控。

C#無法釋放沒有垃圾回收器的對象。如果你釋放一個仍然被引用的對象,當你嘗試使用它時,你的程序會崩潰。這總是存在手動內存管理的風險,但是像所有「內存管理語言」一樣,它試圖防止你犯這種錯誤。如果要顯式關閉對象的操作,請爲該對象的類型實現接口IDisposable,並在該對象上使用Dispose()方法 - 實質上是析構函數。當然,確保你已經完成了它,並且如果在Dispose()d之後嘗試使用它,那麼該對象的行爲將正確(通過拋出異常)。

Objective-C是參考計數的。當一個對象超出引用時,它會自行刪除。 「還有人在使用這個對象嗎?」這不是一個壞的解決方案嗎?問題,除了涉及自己的數據結構;除非仔細處理,否則循環數據結構將永遠存在。 .NET不是一個引用計數器,所以它將擺脫運行代碼無法達到的循環數據結構。

Autorelease只是一個「稍後發佈」,用於返回一個值,如果抓取代碼的代碼不立刻想要保留它,就會自毀。 (不過我不是一個Objective-C程序員)它解決了「誰釋放這個對象?」對於返回一個對象的調用的問題,在函數完成之前沒有銷燬它。儘管如此,這是一個特殊的用例,在大多數情況下它沒有任何意義。

+0

自動釋放可以用於不僅僅是返回值。它可以用來清理函數中的代碼,在這些函數中,您不希望在最終的所有內容中都有發佈,或者您希望創建變量並將其傳遞給另一個函數而不創建引用。自動釋放在開始時可能會非常棘手,但如果您釋放一個對象,它可能會導致問題在您的代碼執行中稍後出現,因爲它可能不清楚問題的原因是什麼。 – skorulis 2010-09-09 03:00:38

+0

我不是Objective-C程序員,所以謝謝你提供的信息!我想編輯我的最後一段更加有用。 autorelease究竟做了什麼?由於某種原因,三分鐘的瀏覽文檔並沒有帶來全面的啓發。 :-) – 2010-09-09 03:08:40

+2

Objective-C確實有一個垃圾收集器,但它僅適用於Mac OS X. – dreamlax 2010-09-09 03:28:54