Quản lý bộ nhớ trong Objective-C
QUẢN
LÝ BỘ NHỚ TRONG OBJECTIVE-C
1. Quản lý bộ nhớ là gì ?
Quản lý bộ nhớ là quản lý việc khởi tạo vùng nhớ cho ứng dụng,
sử dụng nó và giải phóng nó khi ta đã hoàn thành công việc. Một chương trình quản
lý bộ nhớ tốt sẽ sử dụng ít vùng nhớ nhất có thể.
2. Các phương pháp quản lý bộ nhớ trong Objective-C
Objective-C cung cấp 3
cách quản lý bộ nhớ :
• Manual
Reference Counting (MRC)
: Phương pháp đếm số tham chiếu thủ công, có nghĩa là chúng ta sẽ quản lý bộ nhớ bằng cách tự đánh dấu, theo vết vòng đời của một đối tượng, đếm số lượng tham chiếu đến đối tượng đó, kể từ lúc nó được cấp phát, cho đến khi nó được giải phóng.
• Automatic Reference Counting (ARC) : Phương pháp đếm số tham chiếu tự động, nguyên tắc cơ bản tương tự như MRC, tuy nhiên chúng ta không cần phải tự đánh dấu vòng đời của đối tượng nữa, trình biên dịch sẽ làm thay chúng ta phần việc đó.
• Garbage Collection (GC) : Ở phương pháp này hệ thống sẽ tự động lưu vết và giải phóng vùng nhớ của đối tượng không cần thiết nữa. Nó sử dụng kĩ thuật quản lý bộ nhớ khác với MRC và ARC, tuy nhiên GC chỉ hỗ trợ Mac OS X mà không hỗ trợ iOS.
3. Reference Counting
Reference Counting (hoặc Retain Counting) như đã đề cập ở trên, là một phương pháp quản lý bộ nhớ trong Objective-C bằng cách đếm số lượng tham chiếu (Retain Count) đến một đối tượng.
• Khi đối tượng được khởi tạo bằng các từ khóa như alloc, new, copy thì reference count của nó sẽ tự động là
1.
• Để tăng reference count lên 1, ta gửi thông điệp retain cho đối tượng.
• Để giảm reference count xuống 1, ta gửi thông điệp release cho đối tượng.
• Để có thể biết được reference count hiện tại, ta gửi thông điệp retainCount cho đối tượng.
• Khi reference count giảm
xuống 0 thì đối tượng sẽ được hủy, vùng nhớ được giải phóng, lúc này hệ thống sẽ tự
động gửi thông điệp dealloc cho đối tượng.
alloc
retain
release
Khi nào nên sử dụng Autorelease Pool?
Hệ quả từ Autorelease Pool
Khi trong hàm ta sử dụng nhiều biến được cấp phát, và không muốn suy nghĩ lúc nào nên release biến này, lúc nào nên release biến kia, ta chỉ cần kẹp đoạn code giữa NSAutoreleasePool, rồi cho biến đó autorelease, sau đó ta vẫn sử dụng nó được bình thường.
3.1. Cấp phát
Khi cấp phát vùng nhớ cho một đối tượng thì ta sở hữu đối tượng đó. Các phương thức để cấp phát:alloc
- Mục đích: Cấp phát vùng nhớ cho một đối tượng,
- Retain count: 1
copyNSString *str = [[NSString alloc] init];
- Mục đích: Cấp phát vùng nhớ cho một đối tượng thông qua một đối tượng khác
- Retain count: 1
NSString *str = [someString copy];
3.2. Tham chiếu
Khi tham chiếu đến một đối tượng thì ta là đồng sở hữu đối tượng đó, bên cạnh chủ sở hữu của nó. Để gọi tham chiếu ta dùng phương thức retain:retain
- Mục đích: Tham chiếu đến một đối tượng, giống như ta thông báo cho chủ sở hữu của nó là “Đừng xóa nó cho đến khi tôi sử dụng nó xong nhé !”
- Retain count: tăng lên 1.
NSString *str = [[NSString alloc] initWithString:@”Hello”];Trong ví dụ trên, biến str2 chỉ đơn giản là trỏ đến vùng nhớ của biến str, một khi ta giải phóng biến str thì biến str2 sẽ lưu không còn đúng nội dung nữa. Giải pháp:
NSString *str2 = str;
[str release];
NSString *str = [[NSString alloc] initWithString:@”Hello”];str2 vẫn còn lưu đúng nội dung cho tới khi ta giải phóng nó:
NSString *str2 = [str retain];
[str release];
[str2 release];
3.3. Giải phóng
Một đối tượng sẽ thực sự được giải phóng khi không còn ai sở hữu nó nữa, lúc này retain count sẽ bằng 0. Các phương thức để giải phóng:release
- Mục đích: Để giải phóng một đối tượng, báo cho hệ thống biết là ta đã sử dụng xong một đối tượng và cần giải phóng nó.
- Retain count: giảm đi 1 ngay lập tức.
- Mục đích: Để giải phóng một đối tượng nhưng không ngay lập tức, khi ta không muốn phải ghi nhớ lúc nào nên release những đối tượng mà ta đã cấp phát.
- Retain count: giảm đi 1 nhưng không ngay lập tức.
3.3.1. Autorelease object
Là những đối tượng được trả về từ việc gọi hàm, hoặc những đối tượng được gọi bởi phương thức autorelease và ta không sở hữu những đối tượng này. Tất cả các autorelease objects được tạo ra sẽ được thêm vào autorelease pool hiện tại.3.3.2. Autorelease Pool
Là nơi chứa và giải phóng các autorelease objects . Khi autorelease pool được giải phóng (thường là hết vòng lặp hay kết thúc hàm) thì các object nằm bên trong nó cũng sẽ được tự động giải phóng.Khi nào nên sử dụng Autorelease Pool?
- Khi ta muốn tự hủy một loạt các autorelease objects.
- Trong trường hợp cụ thể khi ta sử dụng nhiều biến tạm và muốn tránh phải cấp phát và release tất cả những biến này khi sử dụng xong.
for (int i = 0; i < 99999; i++){Như ví dụ trên đây, nếu như ta không dùng lớp NSAutoreleasePool thì khi chạy hết 99999 vòng lặp, cácautorelease objects nằm trong autorelease pool mới được giải phóng, và điều đó sẽ gây ra hiện tượng tràn bộ nhớ.
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSString *str1 = [NSString stringWithFormat:@”%d”, i];
NSString *str2 = [NSString stringWithFormat:@”%d”, i];
//...
[pool release]; // Các autorelease objects ở trên sẽ đc giải phóng
}
Hệ quả từ Autorelease Pool
Khi trong hàm ta sử dụng nhiều biến được cấp phát, và không muốn suy nghĩ lúc nào nên release biến này, lúc nào nên release biến kia, ta chỉ cần kẹp đoạn code giữa NSAutoreleasePool, rồi cho biến đó autorelease, sau đó ta vẫn sử dụng nó được bình thường.
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
Animal *animal = [[Animal alloc] initWithName:@"Animal"];
[animal autorelease];
Zoo *zoo = [[Zoo alloc] init];
[zoo autorelease];
[zoo add:animal];
[pool release];
Nguồn: LMinh
Nhận xét
Đăng nhận xét