Различия в сообщениях о выпуске и назначении 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.

Другие вопросы по тегам