簡體   English   中英

可可64位二進制文​​件泄漏內存? (釋放NSData不釋放內存)

[英]cocoa 64bit binaries leak memory? (releasing NSData does not free memory)

我一直在玩我的應用程序的不同版本,似乎有些奇怪的事情要發生:

我的應用程序有5mb空閑的足跡。 當保存上傳文件大小的文件時。 上傳后,應釋放保留的內存。 現在構建中存在差異(gc =垃圾收集器):

  • 32位i386 no-GC:立即釋放所有內存。
  • 32位i386 GC:幾乎所有內存都立即被釋放。 其余的一段時間后。
  • 64位x86_64 no-GC:釋放最小內存。 像10%
  • 64位x86_64 GC:根本沒有內存被釋放。 記憶保持數小時。 (活動星期一)

我正在使用LLVM和CLANG。 我一直在運行今天的儀器,並檢查泄漏/僵屍/等。 一切似乎都很干凈。 (該應用程序相當簡單。)

這種行為有解釋嗎?


更新:

那是一些奇怪的東西。 我把問題歸結為:

我將一個20mb的文件加載到NSData中並釋放它。 我這樣做沒有啟用任何垃圾收集。 代碼是:

NSData *bla = [[NSData alloc] initWithContentsOfFile:@"/bigshit"];
[bla release];

當我為i386 32bit構建時,20mb被分配並釋放。 當我將構建切換到64位x86_64時,版本什么都不做。 20mb住宿分配。

上部圖片32位以下64 http://kttns.org/zguxn

兩個應用程序之間沒有區別,除了上面的一個是32位而下面的64位。 沒有GC運行。 (啟用GC后,會出現同樣的問題。)


更新2:

當我從頭開始創建一個新的cocoa應用程序時,可以觀察到相同的行為,只有applicationDidFinishLaunching中的高位代碼: 在64位模式下,內存不會被釋放。 i386按預期工作。

NSString而不是NSData出現同樣的問題。 當我啟動64位內核時,它也會出現。 (啟動時保持64位。)

操作系統是10.6.0

首先,使用Instrument的Object Graph儀器驗證內存不再被認為正在使用中; 在某處沒有保留計數或強引用。

如果它不再使用,那么內存就會因為你沒有達到收集器關心的閾值而堅持下去。

但是,這句話:

64位x86_64 no-GC:釋放最小內存。 像10%

讓我警惕。 具體來說,如果您的代碼設計為在非GC中工作 - 使用retain / release - 那么(a)您有內存泄漏,如果使用CFRetain或某種全局緩存,可能會影響GC或(b)你沒有使用正確的工具來判斷你是否有內存泄漏。

那么,你如何確定你在泄漏記憶?

更新 ; 您正在使用活動監視器來監視進程的RSIZE / VSIZE。 除了“我的流程隨着時間的推移而增長”之外,這實際上並沒有告訴你什么有用。

更可能(我沒有看過源代碼),這段代碼:

NSData *bla = [[NSData alloc] initWithContentsOfFile:@"/bigpoop"];

將導致20MB文件為mmap()進入該進程。 根本沒有涉及malloc()樣式分配。 相反,操作系統將20MB的連續地址空間交給您的進程,並將文件的內容映射到其中。 當您閱讀NSData的內容時,它會在文件中出現頁面錯誤。

釋放bla ,映射將被銷毀。 但這並不意味着VM子系統會將應用程序的地址空間減少20MB。

所以,你正在燒掉一堆地址空間,而不是實際的內存。 由於您的進程是64位,因此地址空間幾乎是無限資源,使用地址的成本非常低,因此操作系統以這種方式實現的原因。

即沒有泄漏,你的應用程序表現正常,GC或沒有。

這是一個常見的誤解,因此,這個問題很明顯。

垃圾收集器不一定立即釋放內存。

在Objective-C垃圾收集器的情況下,您可以向Cocoa的垃圾收集器對象發送一個collectIfNeeded消息,以表明現在可能是進行一些收集的好時機,或者collectExhaustively按順序收集以命令它立即開始收集任何和所有垃圾(但是即使這是可以中斷的)。 查看文檔

我在iPhoneOS 3.2中有一個非常類似的問題,我真的不認為內存正在被回收 - 我最終會觸發內存警告。 我忽略了自己的錯誤的可能性很小,但我已經非常徹底了。

我使用NSKeyedUnarchiver的unarchiveObjectWithFile:來加載包含單個大型NSData和另一個小得多的對象的自定義對象。 我的自定義對象中的dealloc方法被調用,NSData對象被釋放,其retainCount == 1就在之前。 物理內存不會減少任何數量,更不用說NSData大小的一小部分,並且可靠地生成重復內存警告:我已經測試,直到我實際收到2級警告。 =(

發布前:

(gdb)p(int)[(NSData *)pastItsWelcomeData retainCount]
1美元= 1

發布后:

(gdb)p(int)[(NSData *)pastItsWelcomeData retainCount]
目標不響應此消息選擇器。

暫無
暫無

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

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