美文网首页
iOS35 -- 程序内存布局及Tagged Pointer

iOS35 -- 程序内存布局及Tagged Pointer

作者: 恋空K | 来源:发表于2021-03-26 11:23 被阅读0次
    我们平时所写的代码,也就是.h .m文件,编译完成后就会变成01010101...的机器码。这些代码最终是会载
    进内存的,放在内存的代码段。所以代码端就是存放010101...那些代码的,也就是编译后的代码
    函数里面的局部变量都是放在栈里面的,0x7 是十六进制位,转为二进制位是0b0111
    
    变量e,f,g都是放在栈区的(不管有没有初始化),而且e的地址值大于f的地址值,f的地址值大于g的地址值,不断去用栈空间的话,内存地址值是越来越小的---a,c,b,d放在数据段
    内存分布示意图
    int a = 10;
    int b;
    
    int main(int argc, char * argv[]) {
        @autoreleasepool {
            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);
            NSLog(@"---指针地址str=%p\n指针地址obj=%p",&str,&obj);
            
            return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
        }
    }
    --------由打印可知,obj指向的NSObject创建的对象在堆区,而obj指针本身是在栈区
     字符串常量
     str=0x108cbe090
     
     已初始化的全局变量、静态变量
     &c= 0x108cbeea0
       = 0x108cbee98
     &a= 0x108cbee9
     
     未初始化的全局变量、静态变量
     &d= 0x108cbef68
     &b= 0x108cbef6c
     
     堆
     obj=0x6000038dc0c0
     
     栈
     指针地址app=0x7ffee3586c40
     指针地址obj=0x7ffee6f43c48
     指针地址str=0x7ffee6f43c50
     &f=0x7ffee6f43c58
     &e=0x7ffee6f43c5c
    
    
    有标记的指针。能节省很多的内存空间,这都是编译器帮我们做的
    右边的27就是标记tag
    如果存的值太大,就会变成普通的oc对象的存储方式,也就是说如果Tagged Pointer 8个字节存不下的话,就会变成Tagged Pointer之前的存储方式,也就是number3存储的是nsnumber对象在堆空间的地址值。只要是堆空间对象的地址值,最低有效位肯定是0
    总结
    self.name = [NSString stringWithFormat:@"abcdefghijk"];的本质是调用set方法,
    也就是[self setName:(NSString *)]; assign修饰属性,set方法就是直接赋值
    
    copy的修饰的字符串的set方法在arc环境下是这样的。但是arc的本质是转成mrc
    所以copy修饰的字符串的set方法真正底层长这样子。如果上面的修饰词copy变成strong,下面的[name copy]就变成[name retain],但前面的[_name release] 是不变的。也就是不管是copy修饰还是retain修饰,肯定要先释放掉旧的成员变量
    运行程序会crash,因为_name可能同时被多条线程访问,也就是会有多条线程同时调用[_name release]。假如线程1调用了[_name release],把_name释放了,线程2再来调用[_name release],就会造成坏内存访问
    str1指向的是堆空间的一个字符串对象,str2是一个Tagged Pointer指针
    这段代码不会crash,原因右边是一个Tagged Pointer指针,不会调用所谓的set方法,直接是指针赋值。相当于self.name = 0xa00000636261,直接把地址值赋值给self.name了
    类型差异
    判断是否是Tagged Pointer
    此时a就是最高有效位
    这样都不够64位,所以在前面加0填充

    相关文章

      网友评论

          本文标题:iOS35 -- 程序内存布局及Tagged Pointer

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