ARC hoạt động như nào

Chào các bạn, chắc hẳn các bạn cũng nghe nhiều về tính năng này rồi, nhưng đôi khi nhiều người cũng chỉ biết tính năng này để quản lý bộ nhớ thôi. Thì nay mình sẽ viết bài để giải thích xem nó thực sự làm gì. Bài viết này mình không nói về cách code dùng ARC như nào, mà chỉ tập trung vào cách ARC hoạt động ra sao.

1. ARC là gì

ARC là viết tắt của Automatic Reference Counting, là một tính năng nằm trong trình biên dịch. ARC được ra mắt vào bản update iOS 5, cũng khá lâu rồi ?.

2. ARC làm được gì

ARC giúp ta loại bỏ khó khăn trong việc quản lý bộ nhớ. Như trước kia chưa có ARC thì lập trình viên phải thực hiện retain, release, autorelease bằng tay để quản lý bộ nhớ của app. Việc phải thực hiện quản lý thủ công bằng tay như vậy rất dễ gây ra sai sót cũng như khó thống nhất được cách quản lý và cách dùng autorelease giữa các developer với nhau. Đôi khi việc xung đột giữa họ rất dễ xảy ra vì có thể 1 developer nào đó quên không gọi autorelease trong lúc return object ở method là một ví dụ.

Sử dụng ARC khá là đơn giản, bạn chỉ việc lập trình như bình thường mà không cần phải thực hiện retain, release, autorelease nữa mà trình biên dịch sẽ thực hiện giúp bạn thêm vào đúng chỗ.

3. Vậy ARC hoạt động như thế nào?

Để nắm rõ được ARC hoạt động như nào thì sẽ sử dụng công cụ disassembler, ở đây mình dùng Hopper Disassembler để xem code assembly sau khi biên dịch như nào.

ARC giúp ta tự động retain, release, autorelease như nào?

Mình thử nghiệm với đoạn code sau.

#import <Foundation/Foundation.h>
@interface HelloService: NSObject
-(void) run;
@end

@implementation HelloService

-(void) run {
    NSString *helloString = [self getValue];
    NSString *strongRefHelloString = helloString;
    
    NSLog(@"%@", helloString);
}

-(NSString *) getValue {
    NSString *s = @"Hello thanhvu.dev";
    
    return s;
}

@end

int main(int argc, const char * argv[]) {
    HelloService *obj = [[HelloService alloc] init];
    [obj run];
    
    return 0;
}

Thực hiện compile, ta thu được executable file.

Thử dùng disassembler để phân tích xem như nào. Ta xem xét các symbol sau: -[HelloService run], -[HelloService getValue]

Ở đây mình compile với kiến trúc x86_84 và kết quả dưới đây được viết dưới dạng assembly intel syntax.

Trong kết quả trên mình có comment giải thích vào trong code assembly. Bạn nào không hiểu thì có thể đọc code được decompile như sau:

Qua đống lùng bùng, loằng ngoằng kia. Ta có thể thấy compiler đã thực hiện tính năng ARC bằng cách thêm vào đó những đoạn code để gọi hàm retain, objc_storeStrong( trong này sẽ gọi code release và xoá địa chỉ là con trỏ đó nắm giữ bằng cách gọi objc_storeStrong(pointer, 0x0)), objc_autoreleaseReturnValue, objc_retainAutoreleasedReturnValue

Implement của những hàm như objc_storeStrong, objc_autoreleaseReturnValue, objc_retainAutoreleasedReturnValue các bạn có thể ngâm cứu tại đây: http://github.com/opensource-apple/objc4

4. Tổng kết

ARC là một tính năng hay ho mà apple đã đưa vào compiler. Nhờ đó mà lập trình viên iOS chúng ta có thể rảnh rang hơn, với tránh được những rắc rối cũng như đối mặt với tình trạng không thống nhất hoặc quên gọi autorelease.

Cảm ơn các bạn đã đọc bài.

6 Replies to “ARC hoạt động như nào”

  1. bài viết rất hay. hi vọng bạn viết thêm bài về Dependency Injection

    1. Ok b nhé. Mình sẽ sắp xếp thời gian viết về chủ đề đó.

  2. Cám ơn bạn về bài viết. Bài viết này đi sâu về cách chạy ở dưới quá (đoạn code Assembly là mình thua luôn) sẽ khó hiểu cho các bạn mới tiếp cận iOS.

    Có 1 góp ý nhỏ ở 2 chỗ này.

    Phần 1. “ARC là viết tắt của Automatic Reference Counting, là một tính năng nằm trong trình biên dịch LLVM của Apple.”
    Phần 4. Tổng Kết là “ARC là một tính năng hay ho mà apple đã đưa ra cho compiler LLVM của họ.”

    Mình thấy bạn nhấn mạnh 2 lần về ARC và LLVM. Mình nghĩ cần làm rõ về 2 điểm này để tránh người đọc bị nhầm lẫn 2 thằng này với nhau.

    Nếu hiểu đúng thì, LLVM là 1 tập hợp kiến trúc để compile 1 ngôn ngữ lập trình (nó ko thuộc về Apple – tham khảo https://llvm.org/) và khi mình search về Objective-C ARC thì nó trả về tài liệu của CLang – https://clang.llvm.org/docs/AutomaticReferenceCounting.html (là một front-end biên dịch các ngôn ngữ C về cho LLVM). Như vậy thì mình nghĩ bạn có thể tách 2 khái niệm này ra và chỉ đề cập đến ARC của Objective-C thì sẽ đúng hơn.

    Thank bạn.

    Các link mình tham khảo:

    https://llvm.org/
    https://stackoverflow.com/questions/2354725/what-exactly-is-llvm
    https://en.wikipedia.org/wiki/Automatic_Reference_Counting
    https://clang.llvm.org/docs/AutomaticReferenceCounting.html

    1. Cảm ơn góp ý của bạn ạ. Target bài viết này là mình giải thích tận gốc vấn đề, nên có cả code assembly sẽ gây khó hiểu cho newbie, tuy nhiên như vậy mới có thể giải thích kỹ càng được.
      2 khái niệm ARC vs LLVM thì mình nghĩ không nhầm được, vì LLVM là backend compiler còn ARC là 1 tính năng thôi.
      Vấn đề LLVM thì xin lỗi mình hơi nhầm lẫn chút 😀 Cảm ơn b rất nhiều

    2. Mình đã loại bỏ LLVM khỏi bài viết cho đỡ rối theo như lời khuyên của bạn rồi ?
      Cảm ơn góp ý của bạn rất nhiều ?

  3. Thank bài viết

Leave a Reply