Не могу понять, откуда происходит утечка памяти - PullRequest
2 голосов
/ 11 июля 2009

Я в некоторой степени новичок в какао, и я просто не могу понять, почему я получаю всплеск на графике утечек в Инструментах с этим кодом. Кажется, что это небольшая утечка (то есть 16 байт, и объект с утечкой - «Generalblock-16»; это единственный объект с утечкой, который говорит о себе на 100%), и кажется, что он остается такого же размера независимо от того, выберу я только 1 файл или 12 000 файлов. Я дважды щелкнул мышью по каждой строке трассировки стека, отображаемой в расширенном представлении инструментов, и это не привело меня к какой-либо строке в моем коде.

Заранее спасибо за любую помощь, которую вы можете оказать мне.

* 1005 Ю.В. *

P.S .: Если в моем коде нет ничего плохого (в чем я сомневаюсь) и утечка - это просто ошибка или что-то, не связанное с моим кодом, безопасно ли использовать этот код как есть? Приведет ли это к нестабильности в моем приложении, к аварийному завершению или к чему-то в этом роде?

@implementation AppController

-(IBAction)openTheOpenPanel:(id)sender
{
    NSOpenPanel *openThePanel = [NSOpenPanel openPanel];
    [openThePanel setAllowsMultipleSelection:YES];

    if([openThePanel runModal] == NSOKButton)
    {
        NSArray *allTheFiles = [openThePanel filenames];    

        int theNumberOfFiles = [allTheFiles count];

        int i;

        NSMutableDictionary * theDict;
        theDict = [[NSMutableDictionary alloc] init];

        for (i=0; i < theNumberOfFiles; i++) {
            NSString *thisFile = [allTheFiles objectAtIndex:i];
            NSString *theFileNum = [NSString stringWithFormat:@"%i", i];

            [theDict setObject:thisFile forKey:theFileNum]; 
        }

        [theDict writeToFile:@"/tmp/test_file.txt" atomically:YES];

        [theDict release];
    }
}

@end

Ответы [ 7 ]

4 голосов
/ 11 июля 2009

Попробуйте запустить CLang Static Analyzer для вашего кода

http://clang -analyzer.llvm.org /

И исправь все, на что это указывает. Я никогда не видел, чтобы это указывало на что-то, что было не так, хотя иногда я был уверен, что это так. Он особенно хорош в поиске утечек и других справочных вопросов.

1 голос
/ 03 августа 2009

1) Убедитесь, что для NSZombieEnabled не задано значение YES в переменных исполняемой среды.

2) вместо звонка:

theDict = [[[NSMutableDictionary alloc] init] autorelease];

Вы можете просто позвонить:

theDict = [NSMutableDictionary dictionary];

Они, по сути, одно и то же.

1 голос
/ 11 июля 2009

Не то, чтобы это что-то решало, но я рекомендую всегда менять

NSMutableDictionary * theDict;

до

NSMutableDictionary * theDict = nil;

В противном случае theDict возможно будет иметь какой-то странный - и неизвестный - адрес памяти, пока вы не выделите / не инициализируете его. Если вы сделаете это:

NSMutableDictionary * theDict;
if (theDict) {
  // condition is true
}

условие будет выполнено, даже если вы сами не инициализировали theDict.

1 голос
/ 11 июля 2009

Ваш код выглядит хорошо! В том, что вы показали, нет утечек памяти. Если вы хотите, вы можете объявить theDict следующим образом:

theDict = [[[NSMutableDictionary alloc] init] autorelease];

Вызов «autorelease» добавит объект в пул autorelease, и он будет автоматически освобожден после выполнения вашей функции. Это удобно - потому что вы не должны помнить, чтобы позвонить релиз. В любом случае здесь будет работать - хотя.

Утечка в вашем приложении при каждом вызове этой функции или только в первый раз? Если Instruments не показывает вам строку кода, где происходит утечка, скорее всего, это просто что-то в системе. По моему опыту, некоторые небольшие утечки случаются очень часто из-за случайных системных проблем.

EDIT:

Утечка такого размера не должна вызывать нестабильности в вашем приложении. Когда вы ищете утечки памяти, вы должны следить за:

  1. Утечки с участием больших кусков память (объекты NSData или NSImage и т. д.)
  2. Утечки внутри циклов или в функциях вызывается неоднократно (это сложит быть значительным).

Даже на iPhone (где ваше приложение получает около 28 МБ ОЗУ, макс.) Небольшая утечка в 16 или 32 байта не имеет большого значения. Как правило, Instruments сообщает о нескольких утечках прямо при запуске приложения - и это не большая проблема. Вы просто хотите убедиться, что вы не теряете все больше и больше памяти во время работы вашего приложения - потому что серьезный пользователь может продолжать запускать ваше приложение до тех пор, пока не будет утечка всей доступной памяти. ОС не будет повторно использовать утечку памяти, потому что она думает, что ваше приложение все еще использует ее - так что в конечном итоге вы не сможете выделить память для новых объектов.

Надеюсь, это поможет!

0 голосов
/ 11 июля 2009

valgrind , король детекторов утечек, перенесен на OS X . valgrind обнаружит утечку памяти и точно скажет, где находился сайт выделения, и, что еще важнее, что было в стеке вызовов при размещении объекта. valgrind это спасение жизни!

0 голосов
/ 11 июля 2009

В этом коде у вас есть четыре возможные строки, которые могут быть причиной утечки:

  1. NSOpenPanel *openThePanel = [NSOpenPanel openPanel];
  2. [openThePanel setAllowsMultipleSelection:YES];
  3. if([openThePanel runModal] == NSOKButton)
  4. NSArray *allTheFiles = [openThePanel filenames];

Попробуйте закомментировать каждый из них - макетировать данные, когда вы закомментируете вызов openPanel или запрашиваете имена файлов, и для оператора if был вызван вид runModal.

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

0 голосов
/ 11 июля 2009

Эй, ребята! Большое спасибо за ваши быстрые ответы!

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

В случае, если это не мой код, который вызывает утечку, и - как вы упомянули - это просто что-то в системе, как вы думаете, безопасно ли использовать мой код, несмотря на наличие небольшой утечки? или это приведет к нестабильности или сбоям в моем приложении?

Я провел обширное тестирование, как оно есть, и до сих пор оно не показало никаких проблем ни в одном из моих тестов (я только заметил наличие утечки при использовании инструментов).

Еще раз спасибо за вашу помощь!

...