iOS: понимание проблемы с выпуском NSString - PullRequest
0 голосов
/ 06 августа 2011

У меня есть следующий код:

+ (NSDictionary*) JSONRequest: (NSString*)query andWithCredentials:(BOOL)withCredentials
{
if (withCredentials)
{
    NSString *username = [LoginHandler GetUsernameFromNSDefaults];
    NSString *password = [LoginHandler GetPasswordFromNSDefaults];
    NSString *additionalQuery = [NSString stringWithFormat:@"login_username=%@&login_password=%@", username, password];

    query = [NSString stringWithFormat:@"%@&%@", query, additionalQuery];

    [username release];
    [password release];
    [additionalQuery release]; 
}

NSURLRequest *request = [NSURLRequest requestWithURL:  
                         [NSURL URLWithString:query]];  

NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];

NSString *jsonString = [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding];
NSDictionary *results = [jsonString JSONValue];
return results;

[request release];
[response release];
[jsonString release];
[results release];

}

Проблема в выпуске дополнительной строки Query-NSString. Когда я запускаю этот код, он заканчивается BAD-ACCES-EXCEPTION для

[additionalQuery release];

Как только я это закомментирую, код работает нормально.

Теперь, насколько это просто, запустить мое приложение без этой строки кода можно, но мой вопрос: что я не так делаю?

Я генерирую NSString в IF-предложении, затем я CAN только освобождаю его в IF-предложении. Но почему я получил там ошибку?

Ответы [ 6 ]

4 голосов
/ 06 августа 2011

Посмотрите на ваше создание дополнительного запроса

NSString *additionalQuery = [NSString stringWithFormat:@"login_username=%@&login_password=%@", username, password];

С помощью stringWithFormat вы создаете автоматически освобожденный объект NSString. Вы НЕ ДОЛЖНЫ выпускать его вручную в соответствии с правилами управления памятью, поскольку у вас его нет.

У вас есть только то, что вы создали с помощью alloc] init ..] или что-то с новым .. или create .. в имени и, конечно, если вы делаете копию, например mutableCopy.

Так что [дополнительный выпуск релиза] вызывает чрезмерное освобождение объекта и, следовательно, это ПЛОХОЙ ДОСТУП

1 голос
/ 06 августа 2011

Проблема в том, что экземпляр строки создается с использованием метода класса, который начинается с имени класса (stringWithFormat). По соглашению, эти типы методов класса возвращают объект с автоматическим освобождением, освобождая вас от беспокойства об их освобождении, если только вы специально не вызываете retain для возвращаемого объекта.

Если вы хотите выполнить собственное управление памятью на объекте, вы можете изменить свою строку:

NSString *additionalQuery = [NSString stringWithFormat:
    @"login_username=%@&login_password=%@", username, password];

к одному из следующих:

NSString *additionalQuery = [[NSString alloc] initWithFormat:
    @"login_username=%@&login_password=%@", username, password];

или

NSString *additionalQuery = [[NSString stringWithFormat:
    @"login_username=%@&login_password=%@", username, password] retain];

Кроме того, у вас также есть несколько других проблем с этим кодом.

  1. Переменная username не должна быть освобождена, потому что, опять же, по соглашению, метод, из которого вы получаете ее из GetUsernameFromNSDefaults, должен возвращать объект с автоматическим освобождением. Как общее практическое правило, любой метод, отличный от init, должен возвращать объект с автоматическим освобождением. Программисту, не имеющему знаний о базе кода, будет очень трудно подобрать его и изменить без соблюдения этих соглашений.

  2. Переменная request освобождать не нужно, поскольку она создается с помощью метода класса, который возвращает объект с автоматическим освобождением (requestWithURL). Если вы хотите, чтобы он был сохранен вашим кодом, либо позвоните по нему retain, либо используйте метод initWithURL:.

  3. Кроме того, переменная results не сохраняется вами, поэтому ее не нужно освобождать.

0 голосов
/ 06 августа 2011

Когда вы создаете экземпляр объекта, используя удобный метод (тот, который не начинается с нового, alloc или copy), возвращаемый объект автоматически освобождается. Другими словами, вам не нужно явно освобождать его.

Когда вы вызываете метод stringWithFormat, он возвращает автоматически освобожденную строку NSString. Впоследствии вы продолжаете выпускать этот экземпляр NSString ...

[additionalQuery release];

Это отправляет сообщение о выпуске в экземпляр AdditionalQuery. Поскольку это объект с автоматическим выпуском, он добавляется в пул с автоматическим выпуском, который обычно (обычно) находится в потоке основного события. Этот пул часто очищается и впоследствии отправляет сообщение о выпуске каждому из содержащихся в нем объектов. Следовательно, при автоматическом освобождении объекта пул будет искать после отправки сообщения о выпуске.

Ваша EXC_BAD_ACCESS здесь является результатом того, что вы выпустили строку NSString - сбросив количество сохраненных записей до 0 до опустошения пула. Затем пул очищается и пытается отправить сообщение освобожденному объекту.

0 голосов
/ 06 августа 2011

additionalQuery никогда не сохранялось, что я вижу.(stringWithFormat выполняет авто-релиз, поэтому он не считается.)

0 голосов
/ 06 августа 2011

Вам не нужно выпускать его вручную, оно будет выпущено автоматически.([NSString stringWithFormat:] против [NSString initWithString:])

0 голосов
/ 06 августа 2011

вы указали здесь [NSString stringWithFormat: @ "login_username =% @ & login_password =% @", имя пользователя, пароль];

означает, что этот метод будет обрабатывать выделение и освобождение для вашей строки, поэтому «вам не нужно освобождать ее», поэтому удалите строку [extraQuery release];

Кроме того, вы не выделяете строку для имени пользователя и пароля, поэтому нет необходимости освобождать ее.

если вы напишите Nsstring * username = [[NSString alloc] init]; тогда вам нужно выпустить его ..

для получения дополнительной информации об управлении памятью см.

http://marcelsite.heroku.com/posts/5-iPhone-s-alloc-init-new-retain-release-autorelease-copy-

это действительно поможет тебе ...

...