2009-09-05 42 views
13

Tôi đã chơi một số thời gian với các bản dựng ứng dụng khác nhau của tôi và có những điều lạ lùng xảy ra:ca cao 64bit nhị phân bị rò rỉ bộ nhớ? (phát hành NSData không miễn phí bộ nhớ)

ứng dụng của tôi có dấu chân không hoạt động 5mb. khi tải lên bộ nhớ tệp có kích thước của tệp được đặt trước. sau khi tải lên bộ nhớ dành riêng nên được giải phóng. bây giờ có sự khác biệt trong bản dựng (gc = bộ thu gom rác):

  • 32bit i386 no-GC: tất cả bộ nhớ đều được giải phóng ngay lập tức.
  • 32bit i386 GC: gần như tất cả bộ nhớ đều được giải phóng tức thì. phần còn lại một thời gian sau đó.
  • 64bit x86_64 no-GC: bộ nhớ tối thiểu được giải phóng. như 10%
  • GC 64bit x86_64: không có bộ nhớ nào được giải phóng. bộ nhớ vẫn được dành riêng cho giờ. (hoạt động mon)

Tôi đang sử dụng LLVM với CLANG. tôi đã chạy các công cụ ngày nay mọi lúc và đang kiểm tra rò rỉ/thây ma/v.v. và mọi thứ dường như sạch sẽ. (ứng dụng khá đơn giản.)

có giải thích cho hành vi này không?


Cập nhật:

Đó là một số nội dung kỳ lạ. Tôi đã giải quyết vấn đề này:

Tôi tải một tệp 20MB vào một NSData và thả nó ra. Tôi đang làm điều này mà không có bất kỳ bộ sưu tập rác nào được kích hoạt. Mã này là:

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

Khi tôi xây dựng cho i386 32bit 20mb được cấp phát và phát hành. Khi tôi chuyển đổi bản build thành 64bit x86_64 thì bản phát hành không làm gì cả. Thời gian lưu trú 20mb được phân bổ.

upper pic 32bit lower 64 http://kttns.org/zguxn

Không có sự khác biệt giữa hai ứng dụng ngoại trừ việc một thượng được xây dựng cho 32bit và thấp hơn một 64bit. Không có GC chạy. (Với GC được kích hoạt cùng một vấn đề xuất hiện.)


Cập nhật 2:

hành vi tương tự có thể được quan sát thấy khi tôi tạo ra một ứng dụng cacao mới từ đầu chỉ với mã trên trong applicationDidFinishLaunching :. Trong chế độ 64bit bộ nhớ không được giải phóng. i386 hoạt động như mong đợi.

Sự cố tương tự xuất hiện với NSString thay vì NSData. Nó cũng xuất hiện khi tôi khởi động hạt nhân 64bit. (Giữ 64 khi khởi động.)

Hệ điều hành là 10.6.0

+0

Bạn đã thử phân bổ và deallocating rất nhiều trường hợp NSData để xem bộ nhớ cho bất kỳ người trong số họ được khai hoang? Nó có thể là chương trình không trả lại bộ nhớ cho hệ điều hành trừ khi có thiếu bộ nhớ. – Amok

+0

Tôi chỉ cố gắng để tái sản xuất này trên 10.6 mà không có may mắn. Bạn đã gửi lỗi với ứng dụng thử nghiệm của mình chưa? – Ken

+0

Ứng dụng của bạn hoạt động chính xác và không bị rò rỉ bộ nhớ. Xem câu trả lời của tôi bên dưới để biết giải thích bán chi tiết. – bbum

Trả lời

10

Trước tiên, hãy sử dụng công cụ Đồ thị đối tượng của Instrument để xác minh rằng bộ nhớ không còn được coi là đang sử dụng; không có số lần lưu giữ hoặc tham chiếu mạnh ở đâu đó.

Nếu nó không còn được sử dụng nữa, thì bộ nhớ sẽ bám xung quanh đơn giản vì bạn chưa đạt đến ngưỡng mà tại đó người sưu tầm quan tâm.

Tuy nhiên, tuyên bố này:

64bit x86_64 không-GC: bộ nhớ tối thiểu là giải phóng. như 10%

Làm cho tôi cảnh giác. Cụ thể, nếu mã của bạn được thiết kế để hoạt động không phải GC - với việc giữ lại/giải phóng - thì (a) bạn bị rò rỉ bộ nhớ và, nếu sử dụng CFRetain hoặc một số loại bộ nhớ cache toàn cầu, có thể ảnh hưởng đến GC hoặc (b) bạn không sử dụng đúng công cụ để tìm hiểu xem liệu bạn có bị rò rỉ bộ nhớ hay không.

Vì vậy, bạn xác định rằng bạn đang rò rỉ bộ nhớ như thế nào?

Cập nhật; bạn đang sử dụng Activity Monitor để theo dõi RSIZE/VSIZE của quá trình. Điều này sẽ không thực sự cho bạn biết bất cứ điều gì hữu ích ngoài "là quá trình của tôi phát triển theo thời gian".

Nhiều khả năng hơn không (tôi đã không nhìn vào nguồn), mã này:

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

có gây ra các tập tin 20MB là mmap() 'd để quá trình này. Không có sự phân bổ kiểu malloc() nào cả. Thay vào đó, hệ điều hành đưa 20MB không gian địa chỉ tiếp giáp cho quá trình của bạn và ánh xạ nội dung của tệp vào đó. Khi bạn đọc nội dung của NSData, nó sẽ lỗi trang trong tệp khi bạn đi.

Khi bạn phát hành bla, ánh xạ sẽ bị hủy. Nhưng điều đó không có nghĩa là hệ thống con VM sẽ giảm không gian địa chỉ của ứng dụng của bạn xuống 20MB.

Vì vậy, bạn đang đốt cháy một loạt không gian địa chỉ, nhưng không phải là bộ nhớ thực. Kể từ khi quá trình của bạn là 64 bit, không gian địa chỉ là khá nhiều tài nguyên vô hạn và có rất ít chi phí để sử dụng địa chỉ, do đó lý do tại sao hệ điều hành được triển khai theo cách này.

I.e. không có rò rỉ và ứng dụng của bạn hoạt động chính xác, GC hoặc không.

Đây là quan niệm sai lầm phổ biến và do đó, gắn dấu sao cho câu hỏi.

+0

Tôi đang sử dụng các công cụ rò rỉ bộ nhớ. Và như một 32bit xây dựng mọi thứ hoạt động như mong đợi. – jsz

+0

vui lòng đọc nội dung cập nhật của tôi cho câu hỏi gốc. – jsz

+0

cảm ơn câu trả lời. có vẻ như bạn đã đúng :) – jsz

2

Bộ thu gom rác không nhất thiết phải giải phóng bộ nhớ ngay lập tức.

Trong trường hợp của bộ thu rác Objective-C, bạn có thể gửi đối tượng thu gom rác của Cocoa theo thông báo collectIfNeeded để gợi ý rằng bây giờ có thể là thời điểm tốt để thực hiện một số bộ sưu tập hoặc collectExhaustively. tất cả rác (nhưng ngay cả điều này là gián đoạn). Xem the docs.

0

Tôi có một vấn đề rất giống nhau trong iPhoneOS 3.2 và tôi thực sự không nghĩ rằng bộ nhớ đang được khai hoang - cuối cùng tôi kích hoạt cảnh báo bộ nhớ. Có một cơ hội nhỏ mà tôi đã bỏ qua một sai lầm của riêng tôi nhưng tôi đã rất kỹ lưỡng.

Tôi sử dụng unarchiveObjectWithFile NSKeyedUnarchiver: để tải một đối tượng tùy chỉnh có chứa một NSData lớn duy nhất và một đối tượng nhỏ hơn nhiều. Phương thức dealloc trong đối tượng tùy chỉnh của tôi được gọi, đối tượng NSData được giải phóng, là retainCount == 1 ngay trước đó. Bộ nhớ vật lý không giảm bởi bất kỳ số lượng nào, hãy để một mình một phần kích thước NSData, và với cảnh báo bộ nhớ lặp lại được tạo ra một cách đáng tin cậy: Tôi đã kiểm tra cho đến khi tôi thực sự nhận được cảnh báo cấp 2.= (

Trước khi phát hành:

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

Sau khi được thả:

(gdb) p (int) [(NSData *) pastItsWelcomeData retainCount]
Mục tiêu không phản hồi với bộ chọn thư này.

+0

Bạn có một vấn đề khác. GC không tồn tại trên iPhone và 'retainCount' là điều sai để sử dụng để gỡ lỗi các vấn đề về đối tượng suốt đời. (Sử dụng các công cụ thay thế.) Vì đây là một mô tả của một vấn đề khác và nó không trả lời câu hỏi, bạn nên đăng nó như một câu hỏi riêng. –

Các vấn đề liên quan