Я получаю «EXC_BAD_ACCESS» при попытке прочитать строку NSString - PullRequest
3 голосов
/ 18 апреля 2010

Это (очень) упрощенная версия кода моего iPhone:

@ interface x {
NSString * name1;
NSString * name2;
}

-init {
name1 = @ "";
name2 = @ "";
}

- (недействительно) a {
Foo * foo = [Foo alloc];
name1 = @ "uhuh";
name2 = [foo bar]; // вернуть (NSString *)
[выпуск foo];
}

- (недействительно) b {
NSLog (@ "% @", name1); // это работает
NSLog (@ "% @", name2); // там я получаю EXC_BAD_ACCESS ...
}

Почему у меня такая проблема? И как я могу это решить?
Спасибо!

Редактировать: я просто решил проблему, я забыл "сохранить" ...

Ответы [ 3 ]

1 голос
/ 18 апреля 2010

Вам необходимо прочитать Руководство по управлению памятью какао .

Некоторые вещи, которые вы делаете в коде, показывают, что вы не понимаете фундаментальных концепций управления памятью какао.

Например:

[Foo alloc];

Вы не инициализируете 'foo'. Обычной практикой является объединение вызовов alloc и init вместе, например: [[Foo alloc] init]; Это обеспечит то, что члены и состояние объектов соответствуют вашим ожиданиям после создания.

name2 = [foo bar]; // returns a (NSString *)

Метод bar может возвращать строку autoreleased. Вы не сохраните его после присвоения name2, поэтому он будет освобожден через некоторое время после возврата метода. И именно поэтому ваш код падает. Вы пытаетесь получить доступ к освобожденному объекту. Объект, на который указывал name2, был освобожден и освобожден, но указатель не был установлен равным nil, что означает, что память, на которую он указывает, теперь может содержать все что угодно. Это не определено.

Причина, по которой name1 работает, заключается в том, что особое внимание уделяется использованию буквенных @ "" строк в Какао. Когда строка используется таким образом, она становится «интернализованной». Если вы создадите две литеральные строки, содержащие один и тот же текст, система оптимизирует его так, чтобы обе эти строки указывали на один объект в памяти.

То есть, если у вас есть код, который выглядит следующим образом:

NSString *myString1 = @"hello";
NSString *myString2 = @"hello";

NSLog(@"string1: %p, string2: %p", myString1, myString2);

это приведет к тому, что сообщение будет выглядеть так: string1: 0x123456, string2: 0x123456. Здесь важно отметить, что адреса памяти одинаковы. Строки указывают на один и тот же объект, хотя в коде они являются разными экземплярами.

0 голосов
/ 18 апреля 2010

Джоэл прав. попробуй посмотреть твою функцию [foo bar], может быть в той функции ты выпускаешь любой объект

0 голосов
/ 18 апреля 2010

Вчера я получил ошибку EXC_BAD_ACCESS. Оказалось, что я вызывал release для объекта, в результате которого он был удален, затем я попытался использовать его.

Ты не звонишь release на что-то, что тебе не положено?

Просто дружеское напоминание: если вы не вызываете alloc или retain для объекта, вы не вызываете release. С кодом, который вы предоставили, не кажется, что это проблема. Но я хотел указать это на всякий случай.

...