难道栈空间有缓存?

2020-10-30  本文已影响0人  康小曹

最近发现一个有意思的现象,先贴代码:

- (void)viewDidLoad {
    [super viewDidLoad];
    [self test2];
    [self test2];
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [self test2];
}

- (void)test2 {
    NSObject *obj = [NSObject new];
    NSLog(@"caoxk_debug:obj address:%p",&obj);
    NSLog(@"caoxk_debug:obj address:%p",obj);
}

test2 是函数,obj 是栈指针指向了堆空间中的对象实例,按理来说,每次调用 test2,栈空间中的 obj 变量都应该会重新创建,且指向不同的 obj 对象;
执行结果确令人大跌眼镜:

2020-10-29 16:26:48.293 XKHTMLParser[2315:26254180] caoxk_debug:obj address:0x7ffeed57b608
2020-10-29 16:26:48.294 XKHTMLParser[2315:26254180] caoxk_debug:obj address:0x600000007710
2020-10-29 16:26:48.298 XKHTMLParser[2315:26254180] XKObject-dealloc
2020-10-29 16:26:48.298 XKHTMLParser[2315:26254180] caoxk_debug:obj address:0x7ffeed57b608
2020-10-29 16:26:48.299 XKHTMLParser[2315:26254180] caoxk_debug:obj address:0x6080000077c0
2020-10-29 16:26:48.299 XKHTMLParser[2315:26254180] XKObject-dealloc
2020-10-29 16:26:48.301 XKHTMLParser[2315:26254180] caoxk_debug:obj address:0x7ffeed57b948
2020-10-29 16:26:48.301 XKHTMLParser[2315:26254180] caoxk_debug:obj address:0x6080000077c0
2020-10-29 16:26:48.303 XKHTMLParser[2315:26254180] XKObject-dealloc

有时候是:

2020-10-29 16:44:21.230 XKHTMLParser[2867:26309417] caoxk_debug:obj address:0x7ffee8c72608
2020-10-29 16:44:21.231 XKHTMLParser[2867:26309417] caoxk_debug:obj address:0x608000001b60
2020-10-29 16:44:21.231 XKHTMLParser[2867:26309417] XKObject-dealloc
2020-10-29 16:44:21.231 XKHTMLParser[2867:26309417] caoxk_debug:obj address:0x7ffee8c72608
2020-10-29 16:44:21.231 XKHTMLParser[2867:26309417] caoxk_debug:obj address:0x608000001b60
2020-10-29 16:44:21.232 XKHTMLParser[2867:26309417] XKObject-dealloc
2020-10-29 16:44:21.232 XKHTMLParser[2867:26309417] caoxk_debug:obj address:0x7ffee8c72948
2020-10-29 16:44:21.232 XKHTMLParser[2867:26309417] caoxk_debug:obj address:0x608000001b60
2020-10-29 16:44:21.233 XKHTMLParser[2867:26309417] XKObject-dealloc

也就是说,栈中自动变量不会立马销毁,也不一定每次都产生新的栈变量。栈变量所指向的的对象即使 dealloc ,也不一定不是同一个。

可能的原因有两个:

  1. 缓存的优化,一定时间内再次被使用,会使用缓存;
  2. 空间地址一样,但实际上时新创建的对象或者是变量;

具体原因还真不好说,因为即使是:

- (void)viewDidLoad {
    [super viewDidLoad];
    [self test2];
    NSObject *obj1 = [NSObject new];
    NSObject *obj2 = [NSObject new];
    NSObject *obj3 = [NSObject new];
    NSObject *obj4 = [NSObject new];

    [self test2];
}

最后的结果也是:

2020-10-29 16:48:36.847 XKHTMLParser[3038:26321400] caoxk_debug:obj address:0x7ffee1e415e8
2020-10-29 16:48:36.848 XKHTMLParser[3038:26321400] caoxk_debug:obj address:0x6000000153c0
2020-10-29 16:48:36.848 XKHTMLParser[3038:26321400] XKObject-dealloc
2020-10-29 16:48:36.848 XKHTMLParser[3038:26321400] caoxk_debug:obj address:0x7ffee1e415e8
2020-10-29 16:48:36.849 XKHTMLParser[3038:26321400] caoxk_debug:obj address:0x600000015440
2020-10-29 16:48:36.849 XKHTMLParser[3038:26321400] XKObject-dealloc
2020-10-29 16:48:36.849 XKHTMLParser[3038:26321400] caoxk_debug:obj address:0x7ffee1e41948
2020-10-29 16:48:36.849 XKHTMLParser[3038:26321400] caoxk_debug:obj address:0x608000015490
2020-10-29 16:48:36.850 XKHTMLParser[3038:26321400] XKObject-dealloc

如上,虽然对象实例的地址发生了变化,但是栈中的自动变量地址仍然一样。

猜测:
不同于安卓/java/js,垃圾回收机制定时去回收,iOS 中不太可能去做对象或者变量的缓存机制,因为这个量实在太大了。所以,短期内栈或者堆的空间重新被使用,这种解释比较合理。

后续:
汇编方面的知识还是要再复习一遍,堆栈的处理这块应该可以去解释这个现象。另外这个现象也很可能和cpu架构有关,不同的架构可能有不同的处理,不要太过于纠结。

上一篇下一篇

猜你喜欢

热点阅读