浅谈OC内存管理

说到OC的内存管理, 就不得不说一说OC的内存管理机制, OC是通过引用计数, 来决定对象是否释放, 引用计数为0, 对象对应的内存便被释放, 否则, 该片内存就不会被释放。

本文主要大概解释一下内存管理的底层运行机制, 对具体源码实现不做分析, 主要通过定性结论以及一些自己的小demo起到一个科普的作用, 如想深入研究, 网上解析源码的博客不胜枚举, 希望本文能在您深入研究前对您有些许帮助。

MRC时代, 程序员需要自己管理对象的引用计数, 通过retain, release来控制对象的引用计数, 代码冗余不说, 释放非自己持有的对象还会造成crash。笔者并未经历过MRC时代, 没有深刻的体会, 再此不过多赘述, 下面我们聊一聊ARC下的内存管理。

随着ARC的出现, 随之也出现了__strong, __weak指针, 那么它们又各有什么样的作用呢?
作为一名iOS开发者, 不可能对这个问题不知道, 简单来说, strong指针就是对一个对象持有, 使之引用计数+1, 而weak指针仅仅指向该对象, 并不持有该对象, 当该对象被释放时, weak指针自动置为nil。可以看出, weak指针很安全, 至少不会非法访问而造成crash。

那么, 新的问题来了, strong 和 weak关键字的优化各是发生在什么时期呢?

  1. strong指针: 是在编译阶段进行处理, 实际就是编译器给加上 retain release
  2. weak指针: 是在运行期处理, weak指针赋值的时候, 不会对该对象进行retain, 在该对象引用计数为0时, 置为 nil, 事实上是在该对象引用计数即将变为0之前将该指针置为nil(此步骤便是运行期进行处理的)
  3. weak实现原理: 运行时底层会维护一个离散表, 我们可以理解为类似hashMap或NSDictionary结构的东西, 存放所有weak对象的相关信息, {对象地址 : weak指针的指针(二级指针)}, 当对象即将dealloc时, 来检查这个表, 从而改变weak指针的指向, 置为nil

这里我们可以联想到当我们要传一个NSError *error时, 传的是&error, 也是一个二级指针, 只有这样, 才能修改error指针的指向, 如果传的是一级指针, 只能修改指针指向的那块内存的内容。

结论既然已经抛出, 我们用几个小demo来验证一下并加深印象, 首先先说一下大体结构: 有 FirstViewController 和 SecondViewController 两个控制器 SecondViewController 是通过 FirstViewController modal出来的

FirstViewController 中代码

extern id strongVc;
extern __weak id weakVc;
id strongVc = nil;
__weak id  weakVc =  nil;

- (void)touchesBegan:(NSSet<UITouch> *)touches withEvent:(UIEvent *)event {
    NSLog(@"%s, ------------%@", __func__, strongVc); 
    // 当从SecondViewController dismiss回来后, 点击屏幕 BAD_ACCESS 非法访问,
    // 说明调用 dealloc, 不管有没有强引用, 对象对应的那块内存都会被释放
}

SecondViewController 中代码

- (void)viewDidLoad {
    [super viewDidLoad];
    weakVc = self; // 给weakVc赋值
}

- (void)dealloc {
    NSLog(@"weakVc = %@", weakVc); 
    // weakVc = (null), 证明了 调用dealloc完成前, weak指针已经被置为nil

    NSLog(@"self = %@", self); 
     // self = <SecondViewController: 0x7ffe37f0de40>**

    strongVc = self;
    // 此时使一个强指针指向 self 
}

以上注释, 就是操作结果。
此外, 我们知道ARC 不允许主动掉dealloc方法, 那么如果我们强行调用dealloc方法会怎样呢?
在SecondViewController添加以下代码

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    [self performSelector:NSSelectorFromString(@"dealloc")];
    NSLog(@"%s, ------------%@", __func__, weakVc);  // nil
    NSLog(@"%s, ------------%@", __func__, self);   // BAD_ACCESS -> crash
}

强行调用dealloc, 当访问到self时, BAD_ACCESS 导致奔溃, 进一步证明, 只要调用dealloc方法, 会把该对象对应的那部分内存释放。

以上, 是我一些小小的分享, 希望能让大家大体上有个概念, 如果有兴趣进一步了解, 可以研究研究《Objective-C高级编程》, 里面很细致的讲解了与内存管理的相关实现,可以有助于我们更好地了解OC的内存管理机制。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,179评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,229评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,032评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,533评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,531评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,539评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,916评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,813评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,568评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,654评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,354评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,937评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,918评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,152评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,852评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,378评论 2 342

推荐阅读更多精彩内容