这段代码到底会不会奔溃

作者: SmallflyBlog | 来源:发表于2016-11-06 10:26 被阅读149次

以前看书的时候,书上说什么那就是什么,虽然可能不太理解,但还是会给它定义一个「正确」的标准。但是这样会很没有意思,就像是被别人牵着鼻子走似得。如果抱着怀疑的态度去看待,可能会有意思很多,而且还能学到印象深刻的东西。

比如像下面这段代码会不会奔溃的问题:

    void (^block)();
    BOOL condition = /*YES or NO*/;
    if (condition) {
        block = ^{
            NSLog(@"Block A");
        };
    } else {
        block = ^{
            NSLog(@"Block B");
        };
    }
    
    block();

官方的解释是:定义在 if 及 else 语句中的两个块都分配在栈内存中。编译器会给每一个块分配好内存,然而等离开了响应的范围之后,编译器就有可能把分配的块给覆写掉。所以执行结果是有时会奔溃,有时不会奔溃。

疑惑点:

  1. 条件语句中的 Block 赋值给 block 变量,而 block 变量是在条件语句之外的,怎么可能会在 if 语句结束的时候就被销毁呢?
  2. 这个 block 是分配在栈上么?

且来调试一番,我们在 block() 处下一个断点,请看:

__NSGlobalBlock__.png

咦?是 __NSGlobalBlock__ 类型的, 好像被骗了!全局类型的 Block 分配在全局内存区域,会存在于应用程序的整个生命周期,是不会被释放的。

再来看一个例子:

    void (^block)();
    int i = 0;
    BOOL condition = /*YES or NO*/;
    if (condition) {
        block = ^{
            NSLog(@"Block A %d", i);
        };
    } else {
        block = ^{
            NSLog(@"Block B %d", i);
        };
    }
    
    block();

同样断点调试一下:


__NSMallocBlock__.png

什么鬼?又变成 __NSMallocBlock__ 类型了。这里只是让 Block 捕获了一个局部变量 i 怎么就分配到堆内存上去了呢?

我们来进一步分析一下,单独打印这么一段代码:

NSLog(@"%@", [^{NSLog(@"Block A %d", i);} class]);

结果是:

__NSStackBlock__

有没有「全家福」的赶脚?以上类型凑齐了 Block 上层可见的三种类型。

现在我们可以来解释一下,这三种类型是如何演变的。

    block = ^{ NSLog(@"Block A");};

上述代码在 Block 没有捕获外部变量的时候,默认是全局类型的,而当捕获分配在栈上的局部变量 i 时,为了照顾 i 的作用域,就把自己变为了栈类型。

而从栈类型到堆类型是因为执行如下赋值操作,Block 默认会进行一次 copy 操作,把栈上(等式右边)的 Block 复制到堆。

  block = ^{ NSLog(@"Block B %d", i);};

所以我认为正确的答应是:永远不会奔溃。

当然我们讨论的以上情况是在 ARC 环境下。

相关文章

  • 这段代码到底会不会奔溃

    以前看书的时候,书上说什么那就是什么,虽然可能不太理解,但还是会给它定义一个「正确」的标准。但是这样会很没有意思,...

  • indirect_symbol_bindings[i] = cu

    Xcode升级 11.1 RN 项目 运行到 iPhone X是max 上 奔溃: 修改这段代码

  • valueForKeyPath 奔溃

    昨天产品反馈了一个奔溃事件, 因为是做职业教育的, 刚好奔溃在课程上, 因此这里做处理总结。 请问下面代码会奔溃吗...

  • [Point] Android 跳转浏览器

    理想代码如下即可 奔溃日志android.content.ActivityNotFoundException: N...

  • DYLD, Library not loaded: /usr/l

    奔溃日志 奔溃表现:iOS12.1 及以下启动奔溃奔溃日志: 解决方法:关闭bitcode,重新打包上传appst...

  • iOS-千奇百怪的奔溃

    App 上线后,我们最怕的应该就是异常奔溃了。常见的奔溃类型分两种:信号可捕获奔溃、信号不可捕获奔溃,前者比较典型...

  • 奔溃

    送表弟们去上学的路上,听说刚才忘了拿《斗罗大陆》,却又接着说可以向同学借。我的内心立即奔溃了,满满的无力感! 当初...

  • 奔溃

    我总是想不让自己在乎别人的眼光,所以我总是在街上很自在,不担心自己的丑态被别人看到,我也经常对女友这么说,不要在意...

  • 奔溃

    工作到奔溃 加班到晚上八九点 没有人会理解你的苦楚,下班回家星空相伴,人与人之间的关系脆弱到分崩离析,工作后发现身...

  • 奔溃

    为什么当知道这个结果,我却奔溃了?原来不被期待的事情却偏偏来了,心里是那样的抵触。

网友评论

    本文标题:这段代码到底会不会奔溃

    本文链接:https://www.haomeiwen.com/subject/oboguttx.html