Утечка памяти при создании и копировании изображений с помощью NSFiIlemanager в приложении для iPad

#objective-c #ios #nsfilemanager

#objective-c #iOS #nsfilemanager

Вопрос:

У меня утечка памяти, которая приводит к сбою моего приложения при копировании / создании изображений в NSFileManager.

Когда я профилирую свое приложение с помощью «Allocations», все выглядит нормально. Выделяемая память увеличивается примерно с 1,5 МБ до 6 МБ при каждом повторном обращении, а затем снова уменьшается до 1,5 МБ.

Но «Реальная память» и «Виртуальная память» увеличиваются примерно до 150 МБ, а затем приложение выходит из строя.

Я получаю предупреждения о памяти уровня 1 и 2 ранее.

вот функция, которую мы используем:

 -(void) processCacheItems:(NSMutableArray*) originalFiles
{
    if ( [originalFiles count] == 0 )
    {
        [originalFiles release];
        return;
    }
    else
    {
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

        NSString *curFileName = [originalFiles lastObject];
        NSString *filePath = [documentsDirectoryPath stringByAppendingPathComponent:curFileName];
        NSURL *fileURL = [NSURL fileURLWithPath:filePath];

        CGSize destinationSize = CGSizeMake(150,150);
        CGSize previewDestinationSize = CGSizeMake(1440.0, 1440.0);

        UIImage *originalImage = [UIImage imageWithContentsOfFile:filePath]; // AUTORELEASED

        // create thumb and copy to presentationfiles directory
        UIImage *thumb = [originalImage resizedImageWithContentMode:UIViewContentModeScaleAspectFit
                                                             bounds:destinationSize
                                               interpolationQuality:kCGInterpolationHigh]; // AUTORELEASED

        // the resizedImageWithContentMode: does not semm to make the problem, because when i skip this and just use the original file the same problem occours

        NSString *thumbPath = [thumbsDirectoryPath stringByAppendingPathComponent:curFileName];
        [fileManager createFileAtPath:thumbPath contents:UIImageJPEGRepresentation(thumb, 0.9) attributes:NULL];

        // create thumb and copy to presentationfiles directory
        UIImage *previewImage = [originalImage resizedImageWithContentMode:UIViewContentModeScaleAspectFit
                                                                    bounds:previewDestinationSize
                                                      interpolationQuality:kCGInterpolationHigh]; // AUTORELEASED

        NSString *previewImagePath = [previewsDirectoryPath stringByAppendingPathComponent:curFileName];
        [fileManager createFileAtPath:previewImagePath contents:UIImageJPEGRepresentation(previewImage, 0.9) attributes:NULL];


        // copy copy original to presentationfiles directory
        NSString *originalPath = [originalFilesDirectoryPath stringByAppendingPathComponent:curFileName];
        [fileManager copyItemAtPath:filePath toPath:originalPath error:NULL];

        [originalFiles removeLastObject];

        [pool drain];

        [self processCacheItems:originalFiles]; // recursion
    }

}
  

Комментарии:

1. Перейдите в настройки сборки и включите «Запустить статический анализатор».

2. используйте инструмент instrument, чтобы найти место утечки памяти..

3. @iAmitWagh я не вижу этого в инструментах, используя утечки памяти.. В разделе «Распределения» это тоже выглядит неплохо..

4. @WTP. Я включил «Запустить статический анализатор», что я могу видеть теперь? и где?

5. Я не вижу какой-либо очевидной утечки в вашем коде, но использование рекурсии и освобождение массива, когда он пуст, не лучший способ организовать это. Почему бы вам просто не выполнить итерацию по массиву и не освободить его впоследствии? Имя метода processCacheItems: не указывает на то, что он будет освобождать аргумент, который вы ему даете.

Ответ №1:

Спасибо за подсказку.

Мне нравится, что проблема была не в утечке, а в слишком большом распределении памяти при уменьшении размера больших изображений в «resizedImageWithContentMode:» Это привело к сбою приложения.

Я изменил масштабирование изображения, чтобы использовать платформу ввода-вывода изображений. Теперь все работает нормально.

Ответ №2:

ОБНОВЛЕНИЕ: этот ответ устарел. Если вы используете ARC, игнорируйте это.

Как вы распределяете NSFileManager?

Я столкнулся с тем, что выделение его с помощью defaultManager метода, который устарел, приводит к утечкам памяти (или так говорят инструменты, инструменты иногда сообщают об утечках памяти там, где их нет).

Как правило, вы должны выделить его с помощью [[NSFileManager alloc] init] и освободить, когда оно вам больше не понадобится.