//person.h
@interface Person : NSObject
@property(retain, nonatomic) NSString *indexStr;
- (instancetype)initWithIndex:(int)index;
- (void)print;
@end
//person.m
@implementation Person
- (instancetype)initWithIndex:(int)index
{
if (self = [super init]) {
_indexStr = [NSString stringWithFormat:@"%d",index];
NSLog(@"person init index:%d",index);
}
return self;
}
- (void)dealloc
{
self.indexStr = nil;
NSLog(@"person dealloc index:%@",self.indexStr);
[super dealloc];
}
@end
//vc.h
@property (retain, nonatomic) Person *person;
//vc.m
- (void)viewDidLoad {
[super viewDidLoad];
_person = [[Person alloc] initWithIndex:-1];
for (int i = 0; i < 100000; i++) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self actionWrite:@(i)];
});
}
// [NSThread detachNewThreadSelector:@selector(actionRead) toTarget:self withObject:nil];
}
- (void)actionWrite:(NSNumber *)num
{
@synchronized(self) {
self.person = [[[Person alloc] initWithIndex:[num intValue]] autorelease];
}
}
它会在&#34; actionWrith:&#34;崩溃方法。日志是:
2014-09-16 10:11:26.452 testThreadNoARC[1777:149948] person init index:357
2014-09-16 10:11:26.452 testThreadNoARC[1777:149961] person init index:358
2014-09-16 10:11:26.452 testThreadNoARC[1777:149947] person init index:359
2014-09-16 10:11:26.452 testThreadNoARC[1777:149937] person init index:360
2014-09-16 10:11:26.452 testThreadNoARC[1777:149944] person init index:361
2014-09-16 10:11:26.452 testThreadNoARC[1777:149950] person init index:362
2014-09-16 10:11:26.452 testThreadNoARC[1777:149941] person init index:363
2014-09-16 10:11:26.452 testThreadNoARC[1777:149959] person init index:364
2014-09-16 10:11:26.452 testThreadNoARC[1777:149955] person init index:365
2014-09-16 10:11:26.452 testThreadNoARC[1777:149951] person init index:366
2014-09-16 10:11:26.452 testThreadNoARC[1777:149958] person init index:367
2014-09-16 10:11:26.466 testThreadNoARC[1777:149975] person init index:368
2014-09-16 10:11:26.466 testThreadNoARC[1777:149964] person init index:369
2014-09-16 10:11:26.466 testThreadNoARC[1777:149971] person init index:370
2014-09-16 10:11:26.466 testThreadNoARC[1777:149863] *** -[CFString release]: message sent to deallocated instance 0x7fdc5bec77b0
每次都在主题1中崩溃,我不知道为什么会这样快乐。 我认为Person对象已经被释放,可能会再次释放以进行崩溃。 但每次我运行代码时,它的崩溃日志都是一样的。 相同的代码在ARC上运行良好。
答案 0 :(得分:0)
您没有保留用于_indexStr
的字符串。变化:
_indexStr = [NSString stringWithFormat:@"%d",index];
为:
_indexStr = [[NSString stringWithFormat:@"%d",index] retain];
答案 1 :(得分:0)
您的Person
初始化程序中包含以下行:
_indexStr = [NSString stringWithFormat:@"%d",index];
stringWithFormat:
消息返回自动释放的值。您将它直接存储到由retain
属性管理的实例变量中。由于您绕过了setter,因此setter没有机会保留它。一旦自动释放池耗尽,该字符串将被释放。由于您从未保留过它,系统会将其解除分配。现在_indexStr
是一个悬空指针。
稍后,在-[Person dealloc]
中,您执行此操作:
self.indexStr = nil;
由于indexStr
是retain
属性,因此其setter如下所示:
- (void)setIndexStr:(NSString *)value {
NSString *oldValue = _indexStr;
[value retain];
_indexStr = value;
[oldValue release];
}
这意味着当setter执行[oldValue release]
时,它会将release
发送到该悬空指针。这是你崩溃的地方。
最好的办法是停止使用MRC 并开始使用ARC 。
在MRC下,您可以通过多种方式在Person
初始值设定项中正确保留字符串。其中任何一个都可以:
_indexStr = [[NSString stringWithFormat:@"%d",index] retain];
// or
self.indexStr = [NSString stringWithFormat:@"%d",index]
// or
_indexStr = [[NSString alloc] initWithFormat:@"%d", index];