// Option 2
               NSImage                                         *image
           = [[NSImage alloc] initWithContentsOfFile: inPath];

               /* do some stuff */

               [image release];

It seems very likely that the error is in the "do some stuff".

I built an app from your code and sat it in a while loop, and it didn't
leak.  It had the same behavior as you report for the second version of your
code.

-Ken
Cocoa Frameworks

On Wed, Jun 2, 2010 at 6:51 AM, Ken Tozier <kentoz...@comcast.net> wrote:

> Thanks all for the replies
>
> Re point #1: I was using Activity Monitor and both the "Real Memory" and
> "Virtual Memory" columns showed this 100+ MB leak every 5-10 seconds. After
> a minute or so of running, My app had gobbled up almost 2 gigs of memory.
>
> Re point #2: All the thumbnail conversion code is contained within this one
> method, so once it enters the loop, it doesn't exit till it's done.
>
> I tried using [[NSGarbageCollector defaultCollector] collectExhaustively],
> as Jonathan suggested, tried [image setCacheMode: NSImageCacheNever], but
> neither of those slowed the ferocious gobbling of memory.
>
> I finally resorted to using CGxxx functions and the problem disappeared. My
> App now hums along generating 12 to 15 thumbnails per second with a memory
> footprint in the 20 to 30 MB range. Here's what worked:
>
>
> - (NSString *) createJPEGThumbnail:(NSString *) inPath
>                        site:(NSString *) inSite
> {
>        NSDictionary                    *siteRecord,
>                                                        *pubRecord;
>
>        NSString                                *sourceName             =
> [inPath lastPathComponent],
>                                                        *sourceRoot
>             = [sourceName stringByDeletingPathExtension],
>                                                        *destName
>             = [[sourceRoot stringByAddingPercentEscapesUsingEncoding:
> NSUTF8StringEncoding] stringByAppendingPathExtension: @"jpg"],
>                                                        *pubCode
>            = [self pubCodeFromPath: inPath],
>                                                        *thumbPath;
>
>        NSFileManager                   *manager                        =
> [NSFileManager defaultManager];
>
>        siteRecord                              = [thumbDirectories
> objectForKey: inSite];
>
>        pubRecord                               = [[siteRecord objectForKey:
> @"publications"] objectForKey: pubCode];
>
>        if (pubRecord == nil)
>                pubRecord                       = [[siteRecord objectForKey:
> @"publications"] objectForKey: @"~MISCELLANEOUS"];
>
>        thumbPath                               = [[pubRecord objectForKey:
> @"thumb_path"] stringByAppendingPathComponent: destName];
>
>        if (![manager fileExistsAtPath: thumbPath])
>        {
>                NSURL                                           *sourceURL
>            = [NSURL fileURLWithPath: inPath],
>
>  *destURL                = [NSURL fileURLWithPath: thumbPath];
>
>                NSString                                        *imageType
>            = UtilPreferredUTIForFile(inPath);
>                NSNumber                                        *maxPixels
>            = [NSNumber numberWithInt: maxDimension];
>                NSDictionary                            *sourceOptions  =
> [NSDictionary dictionaryWithObjectsAndKeys:
>
>                                            imageType,
> kCGImageSourceTypeIdentifierHint,
>
>                                            kCFBooleanFalse,
> kCGImageSourceShouldCache,
>
>                                            kCFBooleanTrue,
> kCGImageSourceCreateThumbnailFromImageAlways,
>
>                                            maxPixels,
> kCGImageSourceThumbnailMaxPixelSize,
>
>                                            nil];
>
>
>                CGImageSourceRef                        imageSourceCG   =
> CGImageSourceCreateWithURL((CFURLRef) sourceURL, (CFDictionaryRef)
> sourceOptions );
>                if (imageSourceCG != NULL)
>                {
>                        NSDictionary                    *imageProps
>     = (NSDictionary *) CGImageSourceCopyPropertiesAtIndex(imageSourceCG, 0,
> NULL);
>                        int                                             w
>                             = [[imageProps objectForKey: @"PixelWidth"]
> intValue],
>                                                                        h
>                             = [[imageProps objectForKey: @"PixelHeight"]
> intValue];
>
>                        NSRect                          thumbRect
>             = [self thumbRectWithSize: NSMakeSize(w, h)];
>
>                        NSDictionary            *destOptions
>    = [NSDictionary dictionaryWithObjectsAndKeys:
>
>                                    [NSNumber numberWithInt:
> thumbRect.size.width], kCGImagePropertyPixelWidth,
>
>                                    [NSNumber numberWithInt:
> thumbRect.size.height], kCGImagePropertyPixelHeight,
>
>                                    nil];
>
>                        CGImageRef                      imageRefCG
>            = CGImageSourceCreateThumbnailAtIndex(imageSourceCG, 0,
>  (CFDictionaryRef) sourceOptions);
>                        if (imageRefCG != NULL)
>                        {
>                                CGImageDestinationRef   destRef         =
> CGImageDestinationCreateWithURL((CFURLRef) destURL, kUTTypeJPEG, 1, NULL);
>                                if (destRef != NULL)
>                                {
>                                        CGImageDestinationAddImage(destRef,
> imageRefCG, (CFDictionaryRef) destOptions);
>                                        CGImageDestinationFinalize(destRef);
>                                        CFRelease(destRef);
>                                }
>                                CFRelease(imageRefCG);
>                        }
>
>                        CFRelease(imageSourceCG);
>
>                }
>        }
>
>        // make sure it worked
>        if ([manager fileExistsAtPath: thumbPath])
>                return thumbPath;
>        else
>                return nil;
> }
>
>
>
> On Jun 1, 2010, at 6:47 PM, Tony Romano wrote:
>
>  Hi Ken,
>>
>> This code by itself should not be causing a leak.  Couple of questions:
>>
>> 1.  How do you know you have a memory leak?  Sound like a silly question
>> but you didn't tell us anything about what you are using to detect leaks.
>> 2.  Who is calling this code, how many times?  If you are passing the
>> image to something else in the sections you have commented out and you are
>> calling this many times, your memory usage may grow senza any cache'ing that
>> maybe happening.
>>
>> I would suggest putting a NSLog statement at the beginning and look at
>> your output window to make sure the code is not called more than you think.
>>
>> -Tony Romano
>>
>> On May 31, 2010, at 6:41 PM, Ken Tozier wrote:
>>
>>  Hi
>>>
>>> I'm trying to write a thumbnailer class that takes a path to a photo and
>>> creates a thumbnail at a user specified size. The code creates the
>>> thumbnails OK, but there's this monster memory leak, to the tune of about
>>> 100 MB every 3-4 seconds, that seems to be related to NSImage.
>>>
>>> What's happening is that if I comment out the line that initializes a new
>>> image, the memory leak disappears. I've tried forcibly releasing the images,
>>> tried autoreleasing them, tried creating a fixed size buffer into which all
>>> the images are read, nothing seems to work.
>>>
>>> I'm using garbage collection, so that along with the deliberate releasing
>>> of the images, makes me wonder why the collector isn't getting the hint,
>>> that it's ok to release the memory for these photos. Could someone point out
>>> what I'm doing in the following code that prevents the images from getting
>>> released?
>>>
>>> Thanks for any help
>>>
>>> - (NSString *) createJPEGThumbnail:(NSString *) inPath
>>>                        site:(NSString *) inSite
>>> {
>>>        NSDictionary                    *siteRecord,
>>>                                                        *pubRecord;
>>>
>>>        NSString                                *sourceName             =
>>> [inPath lastPathComponent],
>>>                                                        *sourceRoot
>>>               = [sourceName stringByDeletingPathExtension],
>>>                                                        *destName
>>>               = [[sourceRoot stringByAddingPercentEscapesUsingEncoding:
>>> NSUTF8StringEncoding] stringByAppendingPathExtension: @"jpg"],
>>>                                                        *pubCode
>>>              = [self pubCodeFromPath: inPath],
>>>                                                        *thumbPath;
>>>
>>>        NSFileManager                   *manager                        =
>>> [NSFileManager defaultManager];
>>>
>>>        siteRecord                              = [thumbDirectories
>>> objectForKey: inSite];
>>>        pubRecord                               = [[siteRecord
>>> objectForKey: @"publications"] objectForKey: pubCode];
>>>
>>>        if (pubRecord == nil)
>>>                pubRecord                       = [[siteRecord
>>> objectForKey: @"publications"] objectForKey: @"~MISCELLANEOUS"];
>>>
>>>        thumbPath                               = [[pubRecord
>>> objectForKey: @"thumb_path"] stringByAppendingPathComponent: destName];
>>>
>>>        if (![manager fileExistsAtPath: thumbPath])
>>>        {
>>>                // I've tried both of these, didn't make the slightest
>>> difference.
>>>                // Both leaked memory at a furious pace
>>>
>>>                // Option 1:
>>>                NSImage                                         *image
>>>              = [[[NSImage alloc] initWithContentsOfFile: inPath]
>>> autorelease];
>>>
>>>                /* do some stuff */
>>>
>>>
>>>                // Option 2
>>>                NSImage                                         *image
>>>              = [[NSImage alloc] initWithContentsOfFile: inPath];
>>>
>>>                /* do some stuff */
>>>
>>>                [image release];
>>>        }
>>>
>>>        // make sure it worked
>>>        if ([manager fileExistsAtPath: thumbPath])
>>>                return thumbPath;
>>>        else
>>>                return nil;
>>> }
>>> _______________________________________________
>>>
>>> Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)
>>>
>>> Please do not post admin requests or moderator comments to the list.
>>> Contact the moderators at cocoa-dev-admins(at)lists.apple.com
>>>
>>> Help/Unsubscribe/Update your Subscription:
>>> http://lists.apple.com/mailman/options/cocoa-dev/tonyrom%40hotmail.com
>>>
>>> This email sent to tony...@hotmail.com
>>>
>>>
>> -Tony
>>
>>
> _______________________________________________
>
> Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)
>
> Please do not post admin requests or moderator comments to the list.
> Contact the moderators at cocoa-dev-admins(at)lists.apple.com
>
> Help/Unsubscribe/Update your Subscription:
> http://lists.apple.com/mailman/options/cocoa-dev/kenferry%40gmail.com
>
> This email sent to kenfe...@gmail.com
>
_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to