2010-01-05 4 views
4

Если у меня есть этот кодКак я могу надежно освободить память в приложении iPhone?

NSString *postData = [@"foo=" stringByAppendingString:fooText.text]; 
... 
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url]; 
... 
[postData release]; //this causes crash 
[request release]; //this causes crash 

Теперь я понимаю, что это expected behavior according to Apple's documents. Теперь, если я удалю код выпуска, авария не произойдет, но я обнаружил, что утечка памяти в любом случае для * запроса. Поэтому я переписал код

NSString *postData; 
//postData = [NSString alloc]; // this line commented out since OP 
postData = [@"foo=" stringByAppendingString:fooText.text]; 
... 
NSMutableURLRequest *request; 
request = [NSMutableURLRequest alloc]; 
request = [request initWithURL:url]; 
    ... 
    [postData release]; //this still crashes # 
    [request release]; //this works fine 

Я действительно не понимаю, почему он потерпел крах в #. Есть ли рекомендуемая рекомендация? Я думаю, что мне что-то не хватает, потому что я часто вижу «стенографический» подход (сверху), имеющий выпуск (Kochan, Programming in Objective-C, например), но документы Apple говорят, что это неправильно.

ответ

7

Общее правило большого пальца, если вы вызываете вспомогательный статический метод (например, stringByAppendingString), вы не должны его отпускать. Эта строка была добавлена ​​в пул автообновлений, прежде чем вам будут предоставлены. Если вы вызываете alloc, то метод init..., то вы несете ответственность за освобождение этого объекта.

Другие вещи, чтобы отметить в вашем коде:

  • Во втором примере, вы Alloc PostData, а затем сразу же заменить ее на другую строку, созданную stringByAppendingString, то есть утечка памяти.
  • Ваших звонков релизов неправы, они должны быть [postData release] и [request release]
  • Я не видим никакой корреляции между postData и request в вашем примере, поэтому не знает точно, что вы получаете в с двумя из них.
+1

«Общее эмпирическое правило, если вы вызываете вспомогательный статический метод (например, stringByAppendingString), вы не должны его отпускать». Это то, что я искал!Однако как бы я выпустил запрос * в первом примере, учитывая, что инструменты указывают на наличие утечки памяти (все это внутри простого метода). Это, по-видимому, указывает на то, что автореферат не работал для запроса *. – Gazzer

+0

В первом примере вы выделили и ввели запрос самостоятельно, чтобы вы его выпустили. Какая авария вы получаете, когда делаете? EXC_BAD_ACCESS? Это обычно означает, что вы (или что-то, что вы дали запрос) уже выпустили запрос, и вы этого не понимаете. –

0

Выделение памяти для объекта и инициализирует его лучше выполнить в одной строке - метод инициализации может возвращать другой объект, а также может помочь избежать ошибки вы сделали в 2-ом примере:

NSString *postData; // Define pointer to string 
postData = [NSString alloc]; // Allocating nsstring pointer and assign it to variable 
postData = [@"foo=" stringByAppendingString:fooText.text]; // assign to postData new **autoreleased** string object. result of the previous assignment is abandoned. 
[postData release]; //so here you release autoreleased object!! 

Я не могу понять почему [equest release]; Однако причиной аварии является 1-й пример.

P.S. Я не полностью проснусь, или это должно быть [postData release] вместо [release postData]?

1

Во-первых, в вашем втором примере, линия postData = [NSString alloc]; совершенно не нужна - postData переписывается в следующей строке. Во-вторых, чтобы ответить на ваш вопрос о том, почему происходит крушение - нет хорошего ответа - система может выбрать освобождение памяти в любое время после того, как будет отсчитывать количество просмотров. 0. Чтобы более легко отладить проблему, вы должны включить NSZombieEnabled, что немедленно нарисовать любые объекты, которые освобождены, что даст вам 100% надежный способ тестирования сбоев.

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

В целом, вы должны сосредоточиться на соблюдении принципов памяти. Если вы не следуете рекомендациям, поведение может быть неопределенным.

-1
NSString *postData; 
postData = [[NSString alloc]init]; 
postData = [@"foo=" stringByAppendingString:fooText.text]; 
... 
NSMutableURLRequest *request; 
request = [[NSMutableURLRequest alloc]initWithURL:url]; 
... 
    [postData release]; 
    [request release]; 

Попробуйте это.

+0

Ваш пример по-прежнему имеет те же проблемы с postdata, что и в исходном вопросе – Vladimir

+0

его лучше добавить [postData release]; как только вы закончите использовать эту переменную. Вы должны освободить память после ее использования. – Nithin

+1

postData содержит автореализованный объект после назначения в третьей строке - вы не должны его выпускать. и вы выделили строку во 2-й строке, которая просто протекает, поскольку вы просто перезаписываете ее. – Vladimir