26-內(nèi)存管理之內(nèi)存布局+Tagged Pointer+MRC

一 iOS程序的內(nèi)存布局
1653926-dfbc1ea8da8b0598.png
  • 代碼段:編譯之后的代碼

  • 數(shù)據(jù)段

    • 字符串常量:比如NSString *str = @"123"
    • 已初始化數(shù)據(jù):已初始化的全局變量、靜態(tài)變量等
    • 未初始化數(shù)據(jù):未初始化的全局變量、靜態(tài)變量等
  • 棧:函數(shù)調(diào)用開(kāi)銷(xiāo),比如局部變量。分配的內(nèi)存空間地址越來(lái)越小

  • 堆:通過(guò)alloc、malloc、calloc等動(dòng)態(tài)分配的空間,分配的內(nèi)存空間地址越來(lái)越大

代碼例子如下

int a = 10;
int b;

implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    [self test1];
}

- (void)test1 {
    static int c = 20;

    static int d;

    int e;
    int f = 20;

    NSString *str = @"123";

    NSObject *obj = [[NSObject alloc] init];

    NSLog(@"\n&a=%p\n&b=%p\n&c=%p\n&d=%p\n&e=%p\n&f=%p\nstr=%p\nobj=%p\n",
          &a, &b, &c, &d, &e, &f, str, obj);
}

分析結(jié)果如下

/*
 字符串常量
 str=0x1029a4068

 已初始化的全局變量、靜態(tài)變量
 &a =0x1029a4db8
 &c =0x1029a4dbc

 未初始化的全局變量、靜態(tài)變量
 &d =0x1029a4e80
 &b =0x1029a4e84

 堆
 obj=0x60400001b510

 棧
 &f =0x7ffeed25a990
 &e =0x7ffeed25a994
 */

二 Tagged Pointer
  • 從64bit開(kāi)始,iOS引入了Tagged Pointer技術(shù),用于優(yōu)化NSNumber、NSDate、NSString等小對(duì)象的存儲(chǔ)

  • 在沒(méi)有使用Tagged Pointer之前, NSNumber等對(duì)象需要?jiǎng)討B(tài)分配內(nèi)存、維護(hù)引用計(jì)數(shù)等,NSNumber指針存儲(chǔ)的是堆中NSNumber對(duì)象的地址值

  • 使用Tagged Pointer之后,NSNumber指針里面存儲(chǔ)的數(shù)據(jù)變成了:Tag + Data,也就是將數(shù)據(jù)直接存儲(chǔ)在了指針中

  • 當(dāng)指針不夠存儲(chǔ)數(shù)據(jù)時(shí),才會(huì)使用動(dòng)態(tài)分配內(nèi)存的方式來(lái)存儲(chǔ)數(shù)據(jù)

  • objc_msgSend能識(shí)別Tagged Pointer,比如NSNumber的intValue方法,直接從指針提取數(shù)據(jù),節(jié)省了以前的調(diào)用開(kāi)銷(xiāo)

  • 如何判斷一個(gè)指針是否為Tagged Pointer

    • iOS平臺(tái),最高有效位是1(第64bit)
    • Mac平臺(tái),最低有效位是1
三 判斷是否為T(mén)agged Pointer
// 如果是iOS平臺(tái)(指針的最高有效位是1,就是Tagged Pointer)
#   define _OBJC_TAG_MASK (1UL<<63)

// 如果是Mac平臺(tái)(指針的最低有效位是1,就是Tagged Pointer)
#   define _OBJC_TAG_MASK 1UL

- (BOOL)isTaggedPointer:(id)pointer {
    return ((uintptr_t)pointer & _OBJC_TAG_MASK) == _OBJC_TAG_MASK;
}

調(diào)用

// 是否是tagger pointer
- (void)test3 {
    NSNumber *number1 = @4;
    NSNumber *number2 = @5;
    NSNumber *number3 = @(0xFFFFFFFFFFFFFFF);

    NSLog(@"%d %d %d", [self isTaggedPointer:number1], [self isTaggedPointer:number2], [self isTaggedPointer:number3]);
    NSLog(@"%p %p %p", number1, number2, number3);
}

執(zhí)行結(jié)果

1653926-d36430fe6868f000.png

圖解說(shuō)明

1653926-eeba9fd95952611e.png
四 MRC
1.MRC環(huán)境下Set方法內(nèi)部實(shí)現(xiàn)
  • assign修飾
@property (nonatomic, assign) int age;

- (void)setAge:(int)age {
    _age = age;
}

- (int)age {
    return _age;
}

  • retain修飾
@property (nonatomic, retain) Dog *dog;

- (void)setDog:(Dog *)dog {
    if (_dog != dog) {
        [_dog release];
        _dog = [dog retain];
    }
}

- (Dog *)dog {
    return _dog;
}

  • copy修飾
@property (copy, nonatomic) NSArray *data;

- (void)setData:(NSArray *)data {
    if (_data != data) {
        [_data release];
        _data = [data copy];
    }
}

五 OC對(duì)象的內(nèi)存管理
  • 在iOS中,使用引用計(jì)數(shù)來(lái)管理OC對(duì)象的內(nèi)存

  • 一個(gè)新創(chuàng)建的OC對(duì)象引用計(jì)數(shù)默認(rèn)是1,當(dāng)引用計(jì)數(shù)減為0,OC對(duì)象就會(huì)銷(xiāo)毀,釋放其占用的內(nèi)存空間

  • 調(diào)用retain會(huì)讓OC對(duì)象的引用計(jì)數(shù)+1,調(diào)用release會(huì)讓OC對(duì)象的引用計(jì)數(shù)-1

內(nèi)存管理的經(jīng)驗(yàn)總結(jié)
  • 當(dāng)調(diào)用alloc、new、copy、mutableCopy方法返回了一個(gè)對(duì)象,在不需要這個(gè)對(duì)象時(shí),要調(diào)用release或者autorelease來(lái)釋放它

  • 想擁有某個(gè)對(duì)象,就讓它的引用計(jì)數(shù)+1;不想再擁有某個(gè)對(duì)象,就讓它的引用計(jì)數(shù)-1

  • 可以通過(guò)以下私有函數(shù)來(lái)查看自動(dòng)釋放池的情況
    pextern void _objc_autoreleasePoolPrint(void);

// 聲明一
NSMutableArray *data = [[NSMutableArray alloc] init];
self.data = data;
[data release];

// 聲明二
NSMutableArray *data = [NSMutableArray array];
self.data = data;

兩個(gè)聲明方式相同,只是一個(gè)有調(diào)用release操作,一個(gè)沒(méi)有。因?yàn)?code>array內(nèi)部會(huì)調(diào)用autorelease方法。


本文參考:
路飛_Luck (http://www.itdecent.cn/p/07f7b96bb03f)
以及借鑒MJ的教程視頻
非常感謝.


項(xiàng)目連接地址 - MemoryManage-CADisplayLink+Timer

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容