2014-04-30 29 views
5

Tạo một dự án ARC mới và tiêm mã này trong didFinishLaunchingWithOptions.NSNumber rò rỉ bộ nhớ có thể

for (int i=0; i < 1000000; i++) { 
    NSNumber* num = [NSNumber numberWithInt:i]; 
    NSLog(@"%@", num); 
} 

NSLog(@"over"); 

Bộ nhớ của ứng dụng sẽ tăng. Ngoài ra, ở cuối vòng lặp for, bộ nhớ sẽ không giảm.

Tuy nhiên, nếu bạn thay thế trong cùng vòng lặp for:

NSNumber* num = [NSNumber numberWithInt:i]; 

bởi

NSNumber* num = [[NSNumber alloc] initWithInt:i]; 

Sau đó, ký ức sẽ vẫn ổn định.

Đây có phải là hành vi mong đợi không?

EDIT:

Ok, vì vậy chúng ta hãy đặt didFinishLaunchingWithOptions bên cho thời điểm này. Bạn vẫn có thể đặt trong viewDidLoad và xóa số 0 để đến cuối vòng lặp nhanh hơn Bộ nhớ của ứng dụng sẽ tăng lên đến ~ 11 MB. Khi vòng lặp for kết thúc, bộ nhớ sẽ KHÔNG giảm. Nó vẫn ở ~ 11 MB.

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    for (int i=0; i < 100000; i++) { 
     NSNumber* num = [NSNumber numberWithInt:i]; 
     NSLog(@"%@", num); 
    } 

    NSLog(@"over"); 
} 

Nếu bạn đi với:

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    @autoreleasepool { 
     for (int i=0; i < 100000; i++) { 
      NSNumber* num = [NSNumber numberWithInt:i]; 
      NSLog(@"%@", num); 
     } 
    } 

    NSLog(@"over"); 
} 

Surprise! Sự ngạc nhiên! Bạn sẽ có hành vi giống hệt nhau. Bạn sẽ đạt ~ 11 MB và bộ nhớ sẽ KHÔNG giảm. Tuy nhiên, đặt @autorelease bên trong vòng lặp sẽ hoạt động ... Nhưng ở đây, tôi không cố gắng để làm cho mọi thứ hoạt động nhưng hiểu tại sao bộ nhớ không được rút ra ở cuối vòng lặp for.

Vì vậy, câu hỏi vẫn mở.

+0

Thú vị .. Chờ đợi cho các chuyên gia ý kiến ​​về cái này .. – rdurand

+0

gì nếu bạn đặt '@autoreleasepool {...} 'quanh' tuyên bố for'? – trojanfoe

+0

Bạn đã thử với các lớp Foundation khác chưa? Điều gì về một init với một loại (initWithBool: ví dụ)? – rdurand

Trả lời

3

Điều này được mong đợi. Khi bạn phân bổ NSNumber với phân bổ/init, ARC sẽ giải phóng nó ngay sau khi nó không còn cần thiết nữa.

Khi bạn phân bổ nó bằng một phương thức tiện lợi như numberWithInt:, những gì bạn sẽ nhận được là một đối tượng được phân bổ trong một nhóm tự động phát hành. Cho đến khi hồ tự động thoát nước, bộ nhớ của bạn sẽ không được giải phóng. Tuy nhiên, bạn có thể tạo một nhóm tự động trả lời cho vòng lặp của bạn như sau:

for (int i=0; i < 1000000; i++) @autoreleasepool { 
    NSNumber* num = [NSNumber numberWithInt:i]; 
    NSLog(@"%@", num); 
} 

NSLog(@"over"); 

Điều này sẽ giải phóng số sau mỗi lần lặp lại.

Bạn có thể nhận biết thêm chi tiết ở đây: Memory Management Policy

+1

Đây không phải là lý do. Các chủ đề chính đã có một hồ bơi autorelease, được rút ra trên mỗi hop runloop. Những con số này sẽ được giải phóng một lúc sau khi 'application: didFinishLaunchingWithOptions:' thoát. – hamstergene

+0

@trojanfoe có, nó sẽ. – Jorge

+0

Thật vậy. Cú pháp bất thường, mặc dù. – trojanfoe