2011-01-08 28 views
101

Tôi muốn biết bạn đã sử dụng -retainCount trong trường hợp nào và cuối cùng là các sự cố có thể xảy ra khi sử dụng.Khi nào sử dụng -retainCount?

Cảm ơn.

+5

bạn nên ** không bao giờ ** sử dụng '-retainCount'. – holex

+1

(Trừ khi bạn nên. * Rất thỉnh thoảng * hữu ích để giúp hiểu những gì đang xảy ra, miễn là bạn đánh giá cao rằng nó có thể gây hiểu lầm nghiêm trọng vào những thời điểm đó. Và dĩ nhiên, nó hoàn toàn không được phép nếu sử dụng ARC.) –

Trả lời

231

Bạn không bao giờ nên sử dụng -retainCount, vì nó không bao giờ cho bạn biết bất kỳ điều gì hữu ích. Việc triển khai khuôn khổ Foundation và AppKit/UIKit là không rõ ràng; bạn không biết những gì đang được giữ lại, tại sao nó được giữ lại, những người giữ lại nó, khi nó được giữ lại, và như vậy.

Ví dụ:

  • Bạn sẽ nghĩ rằng [NSNumber numberWithInt:1] sẽ có một retainCount của 1. Nó không. Đó là 2.
  • Bạn sẽ nghĩ rằng @"Foo" sẽ có một số retainCount trong số 1. Nó không có. Đó là 1152921504606846975.
  • Bạn sẽ nghĩ rằng [NSString stringWithString:@"Foo"] sẽ có một số retainCount trong số 1. Không. Một lần nữa, đó là 1152921504606846975.

Về cơ bản, vì bất cứ điều gì có thể giữ lại một đối tượng (và do đó thay đổi nó retainCount), và kể từ khi bạn không có nguồn để hầu hết các mã mà chạy một ứng dụng, một retainCount của đối tượng là vô nghĩa.

Nếu bạn đang cố gắng theo dõi lý do tại sao đối tượng không bị phân phối, hãy sử dụng công cụ Rò rỉ trong Công cụ. Nếu bạn đang cố gắng để theo dõi tại sao một đối tượng đã được deallocated quá sớm, sử dụng công cụ Zombies trong Instruments.

Nhưng không sử dụng -retainCount. Đó là một phương pháp vô giá trị.

chỉnh sửa

Hãy tất cả mọi người đi đến http://bugreport.apple.com và yêu cầu -retainCount được phản đối. Càng nhiều người yêu cầu thì càng tốt.

chỉnh sửa # 2

Như một bản cập nhật, [NSNumber numberWithInt:1] bây giờ có một retainCount của 9223372036854775807. Nếu mã của bạn được mong nó sẽ được 2, mã của bạn bây giờ đã bị phá vỡ.

+3

Cảm ơn @ Dave-Delong về các ví dụ của bạn. – Moszi

+1

retainCount hiện hữu ích cho người độc thân. (Bây giờ câu hỏi là hữu ích như thế nào là singletons ...) '- (NSUInteger) retainCount {return NSUIntegerMax;}'. – Joe

+8

@Joe bạn có thể tạo một singleton mà không ghi đè 'retainCount'. –

50

KHÔNG BAO GIỜ!

Nghiêm túc. Chỉ cần không làm điều đó.

Chỉ cần theo dõi Memory Management Guidelines và chỉ phát hành những gì bạn alloc, new hoặc copy (hoặc bất kỳ thứ gì bạn gọi là retain khi ban đầu).

@bbum cho biết nó tốt nhất here on SO và thậm chí chi tiết hơn trên his blog.

+2

tại sao? lý do là gì? – Moszi

+7

Bởi vì bạn sẽ nghĩ rằng bạn đang đếm bộ nhớ, nhưng bạn sẽ làm điều đó sai. – Abizern

+0

@Abizern - và tình huống đơn lẻ ở một trong những câu trả lời khác là gì? – Moszi

3

Bạn có thể gặp vấn đề gì khi sử dụng? Tất cả nó làm là trả lại số lượng giữ lại của đối tượng. Tôi chưa bao giờ gọi nó và không thể nghĩ ra bất kỳ lý do nào mà tôi muốn. Tôi đã ghi đè lên nó trong singletons để đảm bảo rằng họ không deallocated mặc dù.

+2

Không có lý do gì để ghi đè lên nó trong trường hợp đơn. Không có đường dẫn mã trong Foundation/CoreFoundation sử dụng 'retainCount' để quản lý bộ nhớ. – bbum

+0

Không phát hành sử dụng nó để quyết định nếu nó nên gọi dealloc? – ughoavgfhw

+2

Không; việc thực hiện nội bộ của giữ lại/phát hành/autorelease có rễ sâu trong CoreFoundation và thực sự không phải là ở tất cả những gì bạn có thể mong đợi. Đi lấy nguồn CoreFoundation (nó có sẵn) và có một cái nhìn. – bbum

5

Hãy nhìn vào tài liệu của Apple trên NSObject, nó khá nhiều bao gồm câu hỏi của bạn: NSObject retainCount

Nói tóm lại, retainCount có lẽ là vô ích cho bạn trừ khi bạn đã thực hiện hệ thống tính tham khảo riêng của bạn (và tôi có thể gần như đảm bảo bạn sẽ không có).

Nói cách riêng của Apple, retainCount là "thường không có giá trị trong việc gỡ rối các vấn đề quản lý bộ nhớ".

+0

Trước hết, cảm ơn bạn đã trả lời. Thông thường phản ứng của mọi người đối với câu hỏi này là "KHÔNG BAO GIỜ". (Xem câu trả lời). Trên thực tế "không có giá trị trong gỡ lỗi" không có nghĩa là "KHÔNG BAO GIỜ". Vì vậy, câu hỏi của tôi là - tại sao cảm giác mạnh mẽ của việc không sử dụng nó (ví dụ trong thực hiện singleton - một trong những câu trả lời một lần nữa)? – Moszi

+0

Tôi đoán bạn sẽ cần cung cấp thêm thông tin về những gì bạn đang sử dụng. Việc sử dụng có thể chấp nhận được, theo đề xuất của Apple, ghi đè retainCount để thực hiện hệ thống đếm tham chiếu của riêng bạn. Nhưng trong thực tế, bạn sẽ không bao giờ thấy điều đó (tôi chưa bao giờ có, dù sao). Phản ứng mạnh mẽ thường xuất phát từ thực tế chính Apple đã chủ trương (trong các nhóm thư của họ, các tài liệu, diễn đàn dev, vv) để lại retainCount một mình. – lxt

+1

@Moszi: Gỡ lỗi là tình huống duy nhất mà hầu hết mọi người có thể quan niệm về nó có giá trị, vì vậy nếu nó không đáng tin cậy ở đó, nó không bao giờ hữu ích. Bạn đang nghĩ đến cách sử dụng nào khác? – Chuck

3

Bạn không nên lo lắng về việc rò rỉ bộ nhớ cho đến khi ứng dụng của bạn được thiết lập và đang chạy và thực hiện điều gì đó hữu ích.

Sau đó, hãy kích hoạt Công cụ và sử dụng ứng dụng và xem liệu rò rỉ bộ nhớ có thực sự xảy ra hay không. Trong hầu hết các trường hợp, bạn tự tạo một đối tượng (do đó bạn sở hữu nó) và quên phát hành nó sau khi bạn đã hoàn thành.

Đừng cố gắng và tối ưu hóa mã của bạn khi bạn đang viết nó, dự đoán của bạn như những gì có thể bị rò rỉ bộ nhớ hoặc mất quá lâu thường sai khi bạn thực sự sử dụng ứng dụng bình thường.

Hãy thử và viết mã chính xác, ví dụ: nếu bạn tạo một đối tượng bằng cách sử dụng phân bổ và như vậy, sau đó hãy chắc chắn rằng bạn phát hành nó đúng cách.

+0

Trong khi đây là những lời khuyên tốt thường :) - họ không trả lời câu hỏi của tôi ... – Moszi

14

Đối tượng được tự động phát hành là một trong những trường hợp mà việc kiểm tra -retainCount không rõ ràng và có khả năng gây nhầm lẫn. Số lượng giữ lại cho bạn biết không có gì về bao nhiêu lần -autorelease đã được gọi trên một đối tượng và do đó bao nhiêu thời gian nó sẽ được phát hành khi các hồ bơi autorelease hiện tại cống rãnh.

+1

Cảm ơn - đây là một điểm tốt. Đây là câu trả lời đầu tiên thực sự có một lý do được mô tả tại sao không sử dụng retainCount, bên cạnh "không" chung chung. – Moszi

+1

@Moszi: Câu hỏi của bạn là "Khi nào thì sử dụng retainCount?" - nếu bạn không có ý định đặt câu hỏi đó, bạn nên hỏi cái gì khác. – Chuck

+0

@chuck - thực sự tôi đã quan tâm đến "khi nào nên sử dụng nó", tuy nhiên có vẻ như mọi câu trả lời sẽ là "không bao giờ" ... Nhưng - tôi đoán bạn đúng. Tôi sẽ để câu hỏi mở trong một vài ngày, và nếu không có câu trả lời nào khác thì không bao giờ, sau đó tôi sẽ chấp nhận "không bao giờ" như một câu trả lời. – Moszi

10

I do tìm giữ lạiChi tiết rất hữu ích khi được kiểm tra bằng 'Dụng cụ'.

Sử dụng công cụ 'phân bổ', đảm bảo 'Ghi số lượng tham chiếu' được bật và bạn có thể truy cập vào bất kỳ đối tượng nào và xem lịch sử lưu giữCài đặt.

Bằng cách ghép nối allocs và bản phát hành, bạn có thể có được một bức tranh đẹp về những gì đang diễn ra và thường giải quyết những trường hợp khó khăn mà một cái gì đó không được phát hành.

Điều này chưa bao giờ làm tôi thất vọng - bao gồm tìm lỗi trong bản phát hành beta sớm của iOS.

0

Bạn không bao giờ nên sử dụng nó trong mã của bạn, nhưng nó chắc chắn có thể giúp khi gỡ lỗi

0

Không bao giờ sử dụng -retainCount trong mã của bạn. Tuy nhiên nếu bạn sử dụng, bạn sẽ không bao giờ thấy nó trả về số không. Hãy suy nghĩ về lý do tại sao. :-)

2

Tất nhiên bạn không bao giờ nên sử dụng phương pháp retainCount trong mã của bạn, vì ý nghĩa giá trị của nó phụ thuộc vào số lượng autoreleases đã được áp dụng cho đối tượng và đó là điều bạn không thể dự đoán. Tuy nhiên nó rất hữu ích để gỡ lỗi - đặc biệt là khi bạn đang tìm kiếm các rò rỉ bộ nhớ trong mã gọi các phương thức của các đối tượng Appkit bên ngoài vòng lặp sự kiện chính - và nó không nên bị phản đối.

Trong nỗ lực của bạn để làm cho quan điểm của bạn, bạn nghiêm túc phóng đại bản chất không thể hiểu được của giá trị. Đúng là nó không phải luôn luôn là một số tham chiếu. Có một số giá trị đặc biệt được sử dụng cho cờ, ví dụ để chỉ ra rằng một đối tượng không bao giờ nên được deallocated. Một số như 1152921504606846975 trông rất bí ẩn cho đến khi bạn viết nó trong hex và nhận được 0xfffffffffffffff. Và 9223372036854775807 là 0x7fffffffffffffff trong hex. Và nó thực sự không quá ngạc nhiên khi ai đó chọn sử dụng các giá trị như thế này như cờ, cho rằng phải mất gần 3000 năm để có được một số tiền cao hơn số lượng lớn hơn, giả sử bạn tăng số tiền giữ lại 100.000,000 lần mỗi giây.

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