2011-06-30 30 views
9

Tôi đã lập trình trên iPhone khá lâu và đã có những trải nghiệm xấu với việc quản lý bộ nhớ. Tôi đã tự hỏi nếu cách sau đây là một cách tốt để phát hành bộ nhớ.Đây có phải là cách hay để giải phóng bộ nhớ không?

int count = [someObject retainCount]; 

for (int i = 0; i < count; i ++) 
{ 
[someObject release]; 
} 

Phương pháp này là một hành động tuyệt vọng trong một vài trường hợp (đặc biệt là UIWebViews). Số của retainCount của biến được giảm về 0, nó sẽ giải phóng bộ nhớ đang được sử dụng bởi nó. Phương pháp này là một chút bẩn nhưng có bất kỳ tắc nghẽn liên quan đến nó?

+5

Không, đó không phải là cách hay để giải phóng bộ nhớ. – Sneakyness

+0

Vui lòng đọc tài liệu quản lý bộ nhớ của Apple càng sớm càng tốt, giải thích cách bạn quản lý bộ nhớ. Không bao giờ làm điều này. –

Trả lời

28

Bạn không nên dựa vào retainCount vì có khả năng giữ lại các đối tượng bằng cách iOS khung,

đọc dưới đây những gì Apple nói về retainCount.

Quan trọng: Phương pháp này thường là không có giá trị trong bộ nhớ gỡ lỗi vấn đề quản lý. Bởi vì bất kỳ số nào của các đối tượng khung có thể đã giữ lại một đối tượng để giữ tham chiếu với nó, trong khi cùng lúc các nhóm tự động trả lời có thể giữ bất kỳ số phát hành nào là , có thể nhận thông tin hữu ích từ phương thức này.

Để hiểu các quy tắc cơ bản về quản lý bộ nhớ mà bạn phải tuân thủ, hãy đọc “Memory Management Rules”. Để chẩn đoán các vấn đề quản lý bộ nhớ, sử dụng một công cụ thích hợp:

+3

Chưa kể khả năng rằng * một trong các đối tượng của riêng bạn * cũng đang giữ lại đối tượng. Nó không quan trọng đối tượng của nó là ai; nếu bạn đâm vật thể đến chết trong khi một cái gì đó vẫn còn giữ nó, bạn sẽ gây ra một vụ tai nạn sau này. –

3

Bạn không nên dựa vào giá trị của retainCount. Bạn nên phát hành thường xuyên như bạn gọi là alloccopy.

Chỉnh sửa: và newretain.

+0

Và 'giữ lại 'cũng. – beryllium

+0

và 'mới' cũng :) – beryllium

+4

NARC ... phân bổ mới giữ lại bản sao –

14

Mã này là tuyệt đối no-go. Nó chỉ che giấu các lỗi lập trình của bạn - và nó làm như vậy một cách rất xấu.

Vui lòng tìm hiểu cách quản lý bộ nhớ phù hợp. Không có thay thế.

Đây là memory management programming guide. Nó đáng đọc hơn một lần.

+1

Điều này. Một ngàn lần này! –

7

Như những người khác đã đề cập, -retainCount hầu như vô dụng. Khi bạn mới sử dụng tính năng quản lý bộ nhớ/tham chiếu trong Objective-C, đôi khi bạn có thể thử sử dụng - retainCount để hiểu cách tính toán tham chiếu hoạt động, nhưng trên thực tế, có thể (dường như) khó hiểu nhất.

Mã bạn đăng có khả năng gây nguy hiểm, tùy theo ngữ cảnh xung quanh cách sử dụng someObject. Nó cũng có thể nguy hiểm khi áp dụng cho các tình huống khác mà bạn không mong đợi. Hãy liên tục NSString s được tạo bằng cách sử dụng chỉ thị biên dịch @"a string": các chuỗi này được tạo và được thiết kế để không bao giờ được phát hành. Vì vậy, việc áp dụng mã của bạn như trong ví dụ sau sẽ cho kết quả trong một vòng lặp vô hạn:

int main (int argc, const char * argv[]) { 
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 

    NSString *string = @"theString"; 

    NSLog(@"retainCount == %lu", (unsigned long)[string retainCount]); 

    for (NSUInteger i = 0; i < [string retainCount]; i++) { 
     [string release]; 
    } 

    [pool drain]; 
    return 0; 
} 

in này:

2011-06-30 08:40:16.287 retainCount[35505:a0f] retainCount == 1152921504606846975

và sau đó đi vào một vòng lặp vô hạn.

+0

Oooh, tôi đã không nghĩ đến các bức tượng và người độc thân - câu trả lời hay! – deanWombourne

+0

Tôi sẽ không phát hành một hằng số. Tôi biết bản phát hành chỉ cần được gọi là mới, phân bổ, sao chép và giữ lại. Chỉ là trong một vài tình huống, một số vật thể đã giữ được số lượng nhiều hơn tôi mong đợi. Phương pháp tôi đăng chỉ là một công việc xung quanh cho những trường hợp đó. Nhưng từ các câu trả lời được đăng, tôi đoán tốt nhất là theo dõi lý do tại sao nó được giữ lại thay vì sử dụng phương thức đó :). –

+2

Khi nói đến giữ lại số lượng, "nhiều hơn tôi mong đợi" không ngụ ý "không đúng". Bạn cũng không cần phải làm gì để hạ thấp nó - chỉ cần đảm bảo rằng trách nhiệm của chính bạn được thực hiện, các cuộc gọi mới/alloc/retain/copy của bạn đều được cân bằng với bản phát hành (tự động) tương ứng và Mọi chuyện sẽ ổn thôi. Đối với các đối tượng không phải của bạn, hãy nhớ - những gì xảy ra trong NSVegas, vẫn ở trong NSVegas. :-) –

6

Tôi không thể nói KHÔNG đủ mạnh!

Hãy ví dụ này của mã của bạn trong hành động:

// Create an autoreleased object 
MyObject *myObject = [[[MyObject alloc] init] autorelease]; 

// Run your code to make it dealloc itself 
int count = [myObject retainCount]; 
for (int i = 0; i < count; i ++) 
    [myObject release]; 

Mã của bạn sẽ buộc myObject được dealloced.

Tuy nhiên, myObject cũng được đưa vào hồ bơi tự động - ngay khi hồ bơi bắt đầu giải phóng các đối tượng ứng dụng của bạn sẽ bị lỗi vì myObject không còn tồn tại nữa!

Quy tắc rất đơn giản: Phát hành cuộc gọi mỗi khi bạn sử dụng init, new hoặc copy. Nếu không, đó không phải là vấn đề của bạn.

+0

Câu hỏi hay nhất về câu trả lời này là bạn mô tả một vấn đề không phải là ngay cả vấn đề mã mẫu của bạn có. Đó là lý do tại sao bạn nên dựa vào các quy tắc tính tham chiếu (hoặc tính toán tham chiếu tự động hoặc thu gom rác) thay vì cố gắng đoán các khung công tác thứ hai. –

+0

Tôi đang bối rối - cuộc gọi đến stringWithString sẽ thêm myString vào nhóm tự động phát hành - sau đó sẽ cố gắng phát hành nó tại một số điểm trong tương lai. Tôi đang thiếu gì?(Mặc dù rõ ràng, tôi chắc chắn không nói rằng đây là vấn đề _only_ mã OP có, đây chỉ đơn giản là một ví dụ trên một) – deanWombourne

+0

'+ stringWithString:/* một thể hiện của NSConstantString * /' sẽ chỉ trả về hằng số chuỗi, vì vậy bạn đang thực sự cố gắng phát hành một đối tượng tĩnh. Như tôi đã nói, phần quan trọng là nó sai: cố gắng thông minh về cách nó sai sẽ chỉ kết thúc trong nước mắt. –

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