美文网首页
Block小探究心得

Block小探究心得

作者: xiaoliang1 | 来源:发表于2018-12-03 13:29 被阅读117次

    大家经常说blcok是个结构体,每次看到都一堆编译成类c++代码。看着还是很难受。时间久了会不会自己迷糊了。一堆抽象的东西很难受。过一段时间可能忘记了。(现在的面试就有点像应试考试一样。没有实践,没有深入了解)

    在我看来block就只有两种一种是在栈上的,一种在全局区。
    NSConcreteGlobalBlock 全局
    NSConcreteStackBlock 栈上
    NSConcreteMallocBlock 堆上(现在我基本没遇到过直接可以创建,由NSConcreteStackBlock copy,产生)
    既然结构体能在栈上生成么什么异议了。但是也能在堆上创建,但是NSConcreteMallocBlock在堆上的目前我还是没见到的。
    (题话外,object-c 类本质是结构体,苹果却上让他直接alloc new 在堆上(既然是结构体肯定能在栈上))。
    所以,今天我们直接来 NSConcreteGlobalBlock和NSConcreteStackBlock就够了。
    也许大家在用Hopper找一个block函数地址非常头疼,今天看完这个你就不会头疼了。我们就是从hopper里面看block的。
    先来个非常的简单的NSConcreteGlobalBlock

    self.test1 = ^{
    
            NSLog(@"2222");
        };
    
    
        NSLog(@"block: self.test1 class is %@",[self.test1 class]);
    

    打印结果:

    2018-12-03 12:21:53.993461+0800 3333[40992:2030730] block: self.test1 class is __NSGlobalBlock__
    

    Hopper反汇编代码:

    WX20181203-123204@2x.png

    我们只要看___block_literal_global就够了,点击去看看:

    WX20181203-122905@2x.png

    这个第三行0x0000000100001250就是代码函数地址(未在程序载入偏移后),就是代码段的偏移地址,点进去找到看看就是了


    WX20181203-122709@2x.png

    画红线的地方是不是上文的地方对应上了,
    最后一个参数就是描述结构体,这个不用看了。
    ————————————————————————————
    下面来看看NSConcreteStackBlock的这个有点难,
    代码:

    __weak typeof(self)weakself = self;
        void (^pp)(void) = ^{
    
            NSLog(@"1111");
            NSLog(@"%@",weakself);
        };
    
        NSLog(@"block: pp class is %@",[pp class]);
        pp();
    

    打印结果:

    2018-12-03 12:37:13.176667+0800 3333[41749:2041280] block: pp class is __NSStackBlock__
    

    为了更好演示查看别的代码和分析NSConcreteStackBlock,我选择不生成符号变文件和采用release模式来编译这样产生文件


    WX20181203-124641@2x.png WX20181203-124712@2x.png

    在用Hopper查看:

    WX20181203-125742@2x.png

    objc_initWeak 是weakself 的实现。
    点0x100008008进去


    WX20181203-125935@2x.png

    这个玩意就是stackBlock的。被储存在sp+x10的位置
    紧接着是0x100007dc0这个地址,进去你会发现这是会初始化的flag,在全局区。被存储sp+0x18的位置了,和上面只相差8字节,不截图了。从寄存器来看,他只占有2个字节。
    在往下看0x100006654,储存在sp+0x20的位置,点进去才发现这是Block要调用的函数

    WX20181203-130629@2x.png

    是不是上下文地址对上了。

    下面还有还有个地址0x100008100,是blcok的相关描述。这里不用管了。
    从这个分析过程来看stackBlock是在栈区一块连续的内存,依次储存:
    &NSConcreteStackBlock,
    flag,
    funck(blcok要调用的函数),
    block相关表述结构体

    至于堆上的blcok就是栈上copy过去,并不能直接创建,这里不做研究。
    希望这篇文章对你找blcok要调用函数的函数地址有帮助。
    好久都没时间来写东西了,现在把这东西抽空写出来了。
    尊重别人的劳动成果,请不要随便拿去夸夸其谈
    demo:https://github.com/LoveSVN/block-Explore

    相关文章

      网友评论

          本文标题:Block小探究心得

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