美文网首页
runtime-内存访问相关

runtime-内存访问相关

作者: Berning | 来源:发表于2021-09-16 16:08 被阅读0次

    示例

    #import "NSPerson.h"
    
    
    @interface NSWorker : NSPerson
    
    @property NSString *name;
    
    - (void)print;
    
    @end
    
    
    #import "NSWorker.h"
    
    @implementation NSWorker
    
    - (void)person
    {
        [super person];
    
        id cls = [self class];
        void *obj = &cls;
        [(__bridge id)obj print];
        
    }
    
    
    #import "NSWorker.h"
    
    int main()
    {
            [[NSWorker new] person];
    }
    
    
    //log
    2020-08-28 20:10:31.537720+0800 runtime[9289:160822] my name is <NSWorker: 0x10071f120>
    Program ended with exit code: 0
    

    图示

    示意图

    分析1

    对比上图两种方法调用方式,可以看出:
    1>通过obj调用print: 是直接找到NSWorker类,然后调用print
    2>通过worker调用print: 是通过worker对象内部的isa&isa_mask找到NSWorker类,然后调用print

    结论,可以调用成功

    分析2

    两种方式的区别
    1>obj调用print:局部变量obj与cls在函数栈空间是连续的,即局部变量obj与cls(NSWorker)内部isa内存地址是连续的
    2>worker调用print:局部变量worker与函数栈空间其他局部变量是 连续的,worker 调用print是通过worker内部isa & isa_mask找到NSWorker类(isa),所以worker与NSWorker内部的isa的内存地址是不连续的

    结论:print内部访问结构体NSWorker_IMPL的name成员,是访问其isa后面的8个字节
    1>obj调用print:因为obj直接指向了cls = NSWorker_IMPL(isa),所以相当于访问cls后面8个字节,name的值是pls前面的那个局部变量的值
    2>worker调用print:因为worker是间接指向NSWorker_IMPL,所以访问的8个字节的值不会是函数栈空间的其他局部变量

    分析3

    为什么输出结果是my name is <NSWorker: 0x10071f120>

    - (void)person
    {
        [super person];
    
        id cls = [self class];
        void *obj = &cls;
        [(__bridge id)obj print];
        
    }
    
    

    通过分析1和分析2
    person方法内部的局部变量有:

    obj 
    cls
    objc_super  objc_s = {self , [self class]};
    
    

    上面三个地址由低到高,而obj = cls->isa,所以后面8个字节是objc_s的前8个字节,即self(当前对象)

    相关文章

      网友评论

          本文标题:runtime-内存访问相关

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