Ошибки автоматического высвобождения объектов сразу после их создания - PullRequest
1 голос
/ 02 сентября 2011

Я начинаю изучать IOS Development, и у меня есть некоторые сомнения по поводу освобождения объектов, для которых я не хранил ссылку. Я взглянул на вопрос "Выпустить объект без указателя?"где предлагается отправить сообщение об автозапуске объекту сразу после его создания, и поэтому я попытался сделать то же самое в следующем фрагменте кода:

int main(int argc, char *argv[])
{
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    NSURLResponse * response = nil;
    NSError * error = nil;
    NSData * data;

    data = [NSURLConnection
            sendSynchronousRequest: [[NSURLRequest requestWithURL: 
                                        [[NSURL URLWithString: @"http://www.google.it"] 
                                          autorelease] 
                                     ] autorelease]
                 returningResponse: &response
                             error: &error];

    [data writeToFile: @"/tmp/test.html"
           atomically:NO];

    [data release];
    [pool drain];

    return 0;
}

Я не смог выполнить программу вXCode еще нет, но я компилирую под linux, и сообщение об автозапуске, отправленное объекту NSURLRequest, вызывает ошибку сегментации (я думаю, что это вызвано не самим сообщением, а утечкой пула, который пытается освободить объект, из-за автоматического выпускасообщение).Что не так с сообщением об автоматическом выпуске, которое я отправил объекту NSURLRequest?

Я думаю, что если справочный документ для метода класса, такого как requestWithUrl, говорит, что он «создает и возвращает запрос URL», это означает, что я отвечаю за освобождение объекта, когда я закончу его использовать,Я неправ?Я хотел бы очень хорошо понять эти правила управления памятью, прежде чем идти дальше с чем-то еще .. Я надеюсь, что мои вопросы не слишком глупы ;-)

Ну, только один последний вопрос: я должен также выпустить ошибкуа объекты данных возвращаются по синхронному запросу?

Заранее благодарю за любую помощь!

Ответы [ 4 ]

3 голосов
/ 02 сентября 2011

+requestWithURL: (и другие) методы уже возвращают автоматически выпущенные объекты, поэтому вам не следует отправлять им еще одно автоматическое освобождение.

Дополнительные автоматические выпуски в вашем коде приводят к чрезмерному освобождению объекта позже и к аварийному завершению приложения.

Правило большого пальца, чтобы знать, нужно ли освобождать объект - освобождение требуется только в том случае, если вы создаете объект, используя метод, который содержит в своем имени «alloc», «new», «copy».Все стандартные API следуют этому правилу, и вы должны следовать ему при разработке собственных методов.

Таким образом, исправленный код будет:

int main(int argc, char *argv[])
{
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    NSURLResponse * response = nil;
    NSError * error = nil;
    NSData * data;

    data = [NSURLConnection
            sendSynchronousRequest: [NSURLRequest requestWithURL: 
                                            [NSURL URLWithString: @"http://www.google.it"]                                                                                
                 returningResponse: &response
                             error: &error];

    [data writeToFile: @"/tmp/test.html"
           atomically:NO];

    [pool drain];

    return 0;
}

PS Ни объекты данных, ни объекты ошибокдолжен быть освобожден по вышеуказанным причинам.

1 голос
/ 02 сентября 2011

Ваш код должен выглядеть так:

int main(int argc, char *argv[])
{
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    NSURLResponse * response = nil;
    NSError * error = nil;
    NSData * data;

    data = [NSURLConnection
            sendSynchronousRequest: [NSURLRequest requestWithURL:[NSURL URLWithString: @"http://www.google.it"]] returningResponse:&response error: &error];

    [data writeToFile: @"/tmp/test.html"
           atomically:NO];

    [pool drain];

    return 0;
}

Вам не нужно вызывать autorelease к своим объектам, созданным с помощью этих методов. \

Вам не нужно выпускать data и error.

Все методы, которые возвращают объект с использованием следующей нотации NSClass *object = [NSClass classSomeMagicWords];, будут возвращать автоматически освобожденный объект, который вы не должны освобождать, если не вызываете retain.

0 голосов
/ 02 сентября 2011

В управлении памятью iOS вы владеете только теми объектами, которые вы создаете, выделяя для этого память или копируя ее (методы начинаются с alloc или имеют «copy» в названии).

Вам нужно только освободить /Освободите их, если они у вас есть.Такие методы, как requestWithURL или URLWithString, возвращают уже автоматически выпущенные объекты.

Проверьте этот документ на сайте разработчиков Apple для получения дополнительной информации.

0 голосов
/ 02 сентября 2011

Вы должны удалить авто-релизы.В разработке для iOS / Mac OSX классы, предоставляемые Apple, в значительной степени являются правилом, согласно которому, если вы создаете объект с методом, который не включает слово init, вам предоставляется уже автоматически выпущенный объект.

Например:

NSString *blaah = [[NSString alloc] init];

Вернет объект, который нужно отпустить позже.

NSURL *googlelink = [NSURL URLWithString: @"http://www.google.it"];

, с другой стороны, даст вам автоматически выпущенный объект, и если вы отпустите егоопять произойдет сбой.

...