Skip to content

Commit

Permalink
添加悬挂指针
Browse files Browse the repository at this point in the history
  • Loading branch information
100mango committed Sep 18, 2015
1 parent ff61831 commit c3bb858
Showing 1 changed file with 58 additions and 0 deletions.
58 changes: 58 additions & 0 deletions iOS夯实:Crash in Cocoa/Crash in Cocoa.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,62 @@ Cocoa中会导致Carsh的地方:
- (NSString *)substringWithRange:(NSRange)range;
~~~

##2. 访问悬挂指针(Dangling pointer)

悬挂指针,通常也被称为野指针。野指针,指的是指向不正确内存的指针。如果我们访问了不正确的内存,则会导致Crash。

那么什么情况下会导致野指针呢?

- 访问了已被release,但尚未置空的指针

在MRC时代,如果我们提前释放了对象,并且没有把对象置空,再访问这个对象,则会Crash。

~~~objective-c
Person *mango = [[Person alloc]init];
[mango release]; //object此时为野指针
[mango setName:@"mango"]; // Crash:访问了野指针

//正确做法
Person *mango = [[Person alloc]init];
[mango release] //object此时为野指针
mango = nil;
[mango setName:@"mango"]; //向nil发送消息,没有问题
~~~

在ARC时代,编译器会我们进行引用计数的管理。声明为strong,weak的属性,在对象引用计数为零后,自动释放内存,同时将指针置为nil。

那是否就万事大吉了呢。

事实上由于历史原因,UIKit等官方框架里,许多delegate还是声明为assgin而不是weak。(Apple:其实是我懒得改了 :)

声明为assgin和unsafe_unretained的对象,内存被释放后,编译器不会自动将指针置为nil。

像`NSNetServices`的delegate,官方的头文件是这样:

~~~objective-c
@property (assign) id <NSNetServiceBrowserDelegate> delegate;
~~~

类似这样声明的delegate,如果delegate提前被释放,但是我们没有帮助官方的类将delegate置空,如果此时官方的类需要调用到delegate,则同样会造成Crash。

解决方案:

遇到这种旧时代的官方delegate,为了安全起见,我们在dealloc将delegate置为nil

~~~objective-c
- (void)setService:(NSNetService *)service
{
_service = service;
self.service.delegate = self;
[self.service resolveWithTimeout:5];
}

- (void)dealloc
{
// 避免悬挂指针
self.service.delegate = nil;
}
~~~


0 comments on commit c3bb858

Please sign in to comment.