Я не думаю, что есть блокировка dealloc
против retain
/ release
.В следующем примере есть метод dealloc
с sleep()
(кто-нибудь знает, если sleep()
ломает блокировки? Я не думаю, что это так, но вы никогда не знаете).Лучшим примером может быть повторное создание / уничтожение экземпляров A и B до тех пор, пока вы не получите ситуацию, подобную той, которая упоминается здесь, без контроллера sleep()
.
, в моем случае, но может быть что угодно:
-(void)septhreadRetainDel
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSLog(@"[thread#2] sleep(1.f);");
sleep(1.f);
NSLog(@"[thread#2] [b retainDelegate];");
[b retainDelegate];
NSLog(@"[thread#2] sleep(2.f);");
sleep(2.f);
NSLog(@"[thread#2] [b release];");
[b release];
[pool release];
}
- (void)viewDidLoad {
NSLog(@"-(void)viewDidLoad:");
[super viewDidLoad];
NSLog(@"a = [[A alloc] init];");
a = [[A alloc] init];
NSLog(@"[a autorelease];");
[a autorelease];
NSLog(@"b = [[B alloc] init];");
b = [[B alloc] init];
NSLog(@"b.delegate = a;");
b.delegate = a;
NSLog(@"[NSThread detachNewThreadSelector:@selector(septhreadRetainDel) toTarget:self withObject:nil];");
[NSThread detachNewThreadSelector:@selector(septhreadRetainDel) toTarget:self withObject:nil];
}
A:
#import "A.h"
@implementation A
-(void)dealloc
{
NSLog(@"A: dealloc; zzz for 2s");
sleep(2.f);
NSLog(@"A: dealloc; waking up in time for my demise!");
[super dealloc];
}
-(id)retain
{
NSLog(@"A retain (%d++>%d)", self.retainCount, self.retainCount+1);
return [super retain];
}
-(void)release
{
NSLog(@"A release (%d-->%d)", self.retainCount, self.retainCount-1);
[super release];
}
@end
B (.h):
#import "A.h"
@interface B : NSObject {
A *delegate;
}
-(void) retainDelegate;
@property (nonatomic, assign) A *delegate;
@end
B (.m):
#import "B.h"
@implementation B
@synthesize delegate;
-(void)retainDelegate
{
NSLog(@"B:: -(void)retainDelegate (delegate currently has %d retain count):", delegate.retainCount);
NSLog(@"B:: [delegate retain];");
[delegate retain];
}
-(void)releaseDelegate
{
NSLog(@"B releases delegate");
[delegate release];
delegate = nil;
}
-(void)dealloc
{
NSLog(@"B dealloc; closing shop");
[self releaseDelegate];
[super dealloc];
}
-(id)retain
{
NSLog(@"B retain (%d++>%d)", self.retainCount, self.retainCount+1);
return [super retain];
}
-(void)release
{
NSLog(@"B release (%d-->%d)", self.retainCount, self.retainCount-1);
[super release];
}
@end
Программа заканчивается сбоем с EXC_BAD_ACCESS
в методе releaseDelegate.Ниже приведены выходные данные NSLogs:
2010-07-10 11:49:27.044 race[832:207] -(void)viewDidLoad:
2010-07-10 11:49:27.050 race[832:207] a = [[A alloc] init];
2010-07-10 11:49:27.053 race[832:207] [a autorelease];
2010-07-10 11:49:27.056 race[832:207] b = [[B alloc] init];
2010-07-10 11:49:27.058 race[832:207] b.delegate = a;
2010-07-10 11:49:27.061 race[832:207] [NSThread detachNewThreadSelector:@selector(septhreadRetainDel) toTarget:self withObject:nil];
2010-07-10 11:49:27.064 race[832:4703] [thread#2] sleep(1.f);
2010-07-10 11:49:27.082 race[832:207] A release (1-->0)
2010-07-10 11:49:27.089 race[832:207] A: dealloc; zzz for 2s
2010-07-10 11:49:28.066 race[832:4703] [thread#2] [b retainDelegate];
2010-07-10 11:49:28.072 race[832:4703] B:: -(void)retainDelegate (delegate currently has 1 retain count):
2010-07-10 11:49:28.076 race[832:4703] B:: [delegate retain];
2010-07-10 11:49:28.079 race[832:4703] A retain (1++>2)
2010-07-10 11:49:28.081 race[832:4703] [thread#2] sleep(2.f);
2010-07-10 11:49:29.092 race[832:207] A: dealloc; waking up in time for my demise!
2010-07-10 11:49:30.084 race[832:4703] [thread#2] [b release];
2010-07-10 11:49:30.089 race[832:4703] B release (1-->0)
2010-07-10 11:49:30.094 race[832:4703] B dealloc; closing shop
2010-07-10 11:49:30.097 race[832:4703] B releases delegate
Program received signal: “EXC_BAD_ACCESS”.
После вызова -dealloc
сохраняемые значения больше не импортируются.Объект будет уничтожен (это, вероятно, очевидно, хотя мне интересно, что произойдет, если вы проверите self retainCount и НЕ вызовите [super dealloc], если объект сохранил ... безумную идею).Теперь, если мы изменим -dealloc
для A, чтобы сначала установить делегат B на nil
, программа будет работать, но только потому, что мы обнуляем delegate
в B в releaseDelegate
.
Я не знаю, действительно ли это отвечает на ваш вопрос, но если предположить, что sleep () не каким-то образом нарушают блокировки потоков, то же самое должно произойти, когда dealloc
вызывается прямо перед retain
.