秉持着科学严谨的态度,保持着对知识获取的怀疑,对于上一篇博客说,错误的原因,网友们讨论众说纷纭,我们根据主流的几个说法进行逐一验证,找出最科学,最符合逻辑的答案。
1、把 DISPATCH_QUEUE_CONCURRENT这个改成DISPATCH_QUEUE_SERIAL
运行成功未崩溃
缺点:i<1000000,内存开销就跑到了**100.4mb**,单一个for循环语句就跑这么多内存,肯定是不符合要求的
根据上面的测试结果,serial可以让程序正常运行不崩溃,但是内存开销太大,这种方案并不可取。
2、 加上synchronized的加锁代码块,保证每一次语句调用独占该锁
`@synchronized (self) {
self.target = [NSString stringWithFormat:@"ksddkjalkjd%d",i];
NSLog(@"%@",self.target);
}`
运行成功未崩溃
缺点:同上,内存占用资源过大,不可取。
3、 target应该没有被release掉,因为是强引用。问题是出在
[NSString stringWithFormat:@"ksddkjalkjd%d",i]
dispatch_async(queue, ^{
self.target = [NSString stringWithFormat:@"ksddkjalkjd%d",i];
NSLog(@"%p--->,%@",self.target,self.target);
});
在这里打印了指针地址,崩在了i==999939的地方,我们打印一个距离此处较远处的地址
2017-09-14 14:11:12.883 blogTest[9609:766744] 0x608007e44950--->,ksddkjalkjd675959
此时仍然能够打印出675959处的字符串,说明该地址字符串还未被销毁,甚至再找到i值更小的地址打印,结果一样能打印出相应值,那么是在999939处才开始release之前的字符串?所以导致的崩溃?
我们去掉字符串中读取i的地方再运行一次
dispatch_async(queue, ^{
self.target = [NSString stringWithFormat:@"ksddkjalkjd"];
NSLog(@"%@",self.target);
});
运行成功未崩溃
实验表明这个 i 和运行的崩溃息息相关,那么我们思考一下:
在崩溃出po一下这个 i,果然出错了
说明真正正确的答案是,for循环已经走完了,代码块内的局部变量i已经注销了,而异步运行的字符串format那里仍然在调用i,所以崩溃。这样也解释了上面串行、加锁等行为也能阻止崩溃的产生。
所以,别人的博客不一定都是对的,即使是在cocoachina首页上的文章,多试验多思考,找到正确的答案,才有助于自己的提高。