Различия в сообщениях о выпуске и назначении IOS для nsstring
Я проходил через концепции управления памятью. Я создал один string1
и назначить это string1
в другой string2
сейчас выпускаю string1
, Вот string2
сохранить счетчик 1, но на NSLog
Заявление дает EXC Bad доступ.
Когда я назначаю строку
NSString * string1 = [[NSString alloc]initWithFormat:@"hello"];
string2 = string1;
NSLog(@"string1 memory address = %p, string2 memory address = %p", &string1, &string2);
[string1 release];
NSLog(@"[string2 retainCount] = %lu", (unsigned long)[string2 retainCount]);
NSLog(@"string2 = %@", string2); // here app is crashing
Означает ли это, что string2 также имеет сообщение об автозапуске, потому что если я string2 = [string1 copy];
вместо string2 = string1;
это не терпит крах. Итак, я хотел бы спросить, происходит ли сбой, потому что у него есть авто-релиз сообщения string2
и как это связано с string2
отпустить команду. Пожалуйста посоветуй!
1 ответ
Назначение не меняет счет сохранения объекта, если вы используете ручное управление памятью в Objective-C. И вы наверняка используете его, иначе вы не можете вызвать release
метод в вашем коде.
Итак, ваш код делает следующее. Это создает NSString
объект с retain count = 1 и присваивает его string1
указатель. После этого вы назначаете string1
в string2
, Теперь у вас есть 2 указателя на один и тот же объект, и счетчик этого объекта остается равным 1. Затем вы отпускаете объект, он немедленно освобождается. И после этого вы испытываете сбой:
NSString * string1 = [[NSString alloc]initWithFormat:@"hello"]; // string retain count is 1
string2 = string1; // 2 pointers to same string, retain count is still 1
[string1 release]; // string is deallocated when retain count drops to 0
NSLog(@"string2 = %@", string2); // here app is crashing
Чтобы это исправить, вы можете использовать retain
когда вы делаете назначение.
NSString * string1 = [[NSString alloc]initWithFormat:@"hello"]; // string retain count is 1
string2 = [string1 retain]; // 2 pointers to same string, retain count is 2
[string1 release]; // string retain count back to 1
NSLog(@"string2 = %@", string2); // no crash
Также вы можете использовать copy
, Обратите внимание, что для NSString
копия на самом деле не копирует объект, она просто вызывает retain
, Нет необходимости выполнять фактическое копирование, потому что NSString
неизменен и не может быть изменен Если мы будем использовать NSMutableString
, все изменится:
NSMutableString * string1 = [[NSMutableString alloc]initWithFormat:@"hello"]; // string retain count is 1
NSMutableString * string2 = [string1 copy]; // 2 separate strings, both have retain count 1
[string1 release]; // string1 is deallocated
NSLog(@"string2 = %@", string2); // no crash, string2 retain count is 1
Кроме того, вы можете использовать ARC. Он будет вставлять соответствующие вызовы сохранения / освобождения во время компиляции. Код тогда будет выглядеть так:
NSString * string1 = [[NSString alloc]initWithFormat:@"hello"];
string2 = string1;
string1 = nil;
NSLog(@"string2 = %@", string2); // no crash
Я предлагаю сначала разобраться с ручным управлением памятью, а после этого перейти на ARC.