2013-05-28 2 views
1

В моем понимании, если включено ARC, объекты внутри @autoreleasepool{} должны быть выпущены, когда они больше не используются.Объектив C - память утечки autoreleasepool и ARC

Однако код

#import <Foundation/Foundation.h> 

int main(int argc, const char * argv[]) 
{ 
    @autoreleasepool { 
     for (int i = 0; i < 1000000000; i++) { 
      NSString *string = @"ab c"; 
      NSArray *array = [string componentsSeparatedByString:string]; 
     } 
    } 
    return 0; 
} 

утечки памяти.

Приборы показывают, что утечка объектов будут __NSArrayM созданы - [NSString componentsSeparatedByString:]

Итак, вопрос: почему __NSArrayM объекты не уничтожаются в одной и той же итерации цикла они созданы?

Может ли мне помочь в решении этой проблемы

Обновление: Спасибо за ответы, мне кажется, я использовал термин «утечка памяти» неправильно, и непонятых хау @autoreleasepool{} работы. Чтобы решить проблему, я должен был разместить @autoreleasepool{} внутри цикла for.

+2

Этот код выделяет много памяти, но не течет. – stosha

+0

Если вы знаете, что это вызывает утечку, зачем делать такую ​​большую петлю, чтобы доказать это, а не только одну итерацию? :) –

+1

Я на самом деле думаю, что это очень хороший пример вопроса. Я не знаю, почему он собрал так много downvotes. –

ответ

3

чтобы понять, как работает autorelease, сравните этот код в ваш оригинал:

for (int i = 0; i < 1000000000; i++) 
{ 
    @autoreleasepool 
    { 
     NSString* string = @"ab c"; 
     NSArray* array = [string componentsSeparatedByString:string]; 
    } 
} 

Auto выпустила объекты помечаются для освобождения, когда они выходят за рамки, но на самом деле не выпущен ООН до конца секции автореферата (где пул авторезистов сливается).Таким образом, вышеприведенный код будет выделять отмеченные объекты каждый раз вокруг цикла, тогда как ваш исходный код будет освобождать их только в конце цикла.

Пулы с автоматическим высвобождением могут быть вложенными, ближайший используется, когда объект автореализован. Это позволяет вам возвращать объекты из таких функций, как [NSString stringWithFormat:@"%d", i]; - возвращаемая строка имеет значение удержания 1, но отмечено для автоматического выпуска - вы можете использовать ее временно, но если вам нужно сохранить ее для дальнейшего использования, вам необходимо ее сохранить (что происходит, когда вы назначаете его сильной ссылке). Поэтому, когда вы его сохраняете, счетчик удержания переходит в 2, а затем, когда он автоматически отпущен, счет сохранения равен 1, и все это хорошо. Если вы никогда не сохраните его, то при автоматическом выпуске счетчик удержания переходит в 0 и объект будет отменен.

3

Ваше понимание является неправильным

  1. Это не имеет ничего общего с ARC
  2. Это не сбор мусора, так что объекты не будут освобождены, когда они перестают быть использованы
  3. Autorelease бассейн высвобождает объекты когда он слит ([NSAutoreleasePool drain]) или уничтожен. Вы не дренируете бассейн явно, поэтому он будет слит только один раз, перед return.
+0

Даже GC будет иметь смысл, если вы попытаетесь выделить 1 миллиард объектов, подобных этому – CodaFi

+0

@CodaFi Ну, GC может легко освобождать объекты после каждой итерации. Однако более серьезной проблемой будет цикл «почти бесконечный», который может остановить работу других потоков. Это действительно зависит от реализации GC. – Sulthan

+0

Сборщик мусора OS X бежал по второстепенной второстепенной нити IIRC, поэтому я задаюсь вопросом, как «остановить-мир» было бы в этих ситуациях (но это, вероятно, просто переполнило бы цикл) – CodaFi

3

В моем понимании, если ARC включена, объекты внутри @autoreleasepool {} должны быть освобождены, когда они больше не используются.

ОК, сделайте шаг назад и подумайте об этом на секунду. ARC не является каким-то волшебным уловом для каждой утечки памяти, он по-прежнему является ручным удержанием, только компилятор вставил ручную фиксацию. @autoreleasepool {} не избавляет от необходимости предусмотрительности при предоставлении примеров «утечек памяти» и не дает вам права выделять 1 миллиард объектов и называть его ошибкой в ​​структуре. Как оказалось, то, что вы сделали, вероятно, перегрузило пул авторесурсов, которым вы его управляете, и вы либо не дожидаетесь достаточно долго, чтобы цикл завершился нормально, либо вас убили ОС (я бы поставил больше на последнем, чем на первом). Запустив это самостоятельно, я могу подтвердить, что данный пул авторешетки убирает выделенные ОЗУ, это занимает довольно много времени.

Если удалить петлю, или даже сократить его продолжительность (100 или даже 1000 должно хватить), вы можете увидеть, что нет абсолютно никакой утечки объектов, и что все идет путь динозавра правильно:

enter image description here

+0

Очень хороший ответ , – Mike

Смежные вопросы