I'm building an app that uploads resized versions of many images to the server, and I seem to have a memory leak that I can't track down. Here's my method that creates the multi-part request (using Restkit 0.2):

Note that I started using these after I experienced a similar memory leak using UIImageJPEGRepresentation() on a method that turned the CGImageRef into a UIImageinstead.

I'm pretty sure that there's a memory leak because the app eventually terminates due to a memory error. When I run instruments on it, there are tons of living malloc 464/592/398 KB allocations, which instruments gives this stack for:

My initial reaction is that you're creating a lot of images and holding them in memory for transmission (the appendPartData part) Is it possible that you're just running out of memory without an actual leak? Can you write the individual images to temporary files and then use RestKit to upload those?
–
David BerryMay 6 '14 at 21:01

Thanks David, but the multipart form request is only posting a single image at a time. There are 2 threads uploading, so there should only be 2 images in memory at any given time. On my 5S it gets through hundreds of images successfully before running out of memory. I also have a second function that does almost exactly the same thing but posts a batch of 100 thumbnails at the same and does not seem to trigger this leak, which makes it all the more baffling to me.
–
hbridgeMay 6 '14 at 21:54

I'm trying to do something on OSX that is almost identical and observing the same problem. Did you figure out a workaround or resolve this in some other way?
–
Fitter ManMar 13 at 20:04

Sorry, not that I recall, I stopped working on the app that uploaded all the thumbnails shortly after.
–
hbridgeMar 16 at 16:49

2 Answers
2

I looked over your code pretty carefully and the memory management appears sound. You have the key bits enclosed in @autoreleasepool blocks, so any autorleased objects should be cleaned up. Your handling of CF objects also looks correct. (Admittedly memory bugs can be hard to spot...)

If you get a similar sort of leak when using the system method UIImageJPEGRepresentation, it starts to smell more and more like a system bug. Have you tested it against different OS versions (on device). It might be that this leak is new to iOS 7, and does not show up in older iOS versions. If so, it's important to make Apple aware of the bug quickly so they actually fix it in 7, rather than ignoring it until iOS 8 is released.

And have you tested it on device as well as on the sim? I have, more than once in the past, spent a lot of time trying to track down apparent memory leaks when running my code on the sim, only to conclude that the bug was actually in the simulator implementation of system libraries, and the exact same code did not leak when run on a device.

I would suggest submitting 2 bugs to Apple's bug reporter system: The leak in your UIImageJPEGRepresentation approach, as well as the leak in the CGImageSourceCreateThumbnailAtIndex approach. Provide minimal test applications in both cases, or Apple's wonderful (read clueless) bug screeners will kick it back to you immediately.

Once the front-line bug screeners run out of stupid reasons to kick it back to you, they should submit it to the real engineers, who can determine if it really is a framework bug or not. (Can you tell I have a low opinion of the first-level bug screeners at Apple?)

Thanks Duncan, I've come to the same conclusion. I'm definitely running on device (iPhone 5S). After continuing to bang my head against the wall, I tried replacing just the call to CGImageDestinationFinalize(destRef); with a for loop that puts 400K of 0's in the mutabledata object instead, and the memory leak vanished, which makes me pretty confident I'm not hanging on to it in the wrong way. I'll try making a repro app and submitting to Apple as you suggest. Thanks for taking the time to look over my memory management in detail!
–
hbridgeMay 7 '14 at 20:23

Hello insane-36, I'm looking for an NSData object as the output, not a UIImage. As I mentioned in the post, I tried using a function that resizes the image, then using UIImageJPEGRepresentation to turn it into NSData, but I had the same leak. I tried substituting my image resize code for what you posted, since it does look simpler, but I had to modify it a bit (CGImageSourceCreateWithURL takes an options dict, url I set from asset.defaultRepresentation.url) and get an error: <Error>: ImageIO: CGImageSourceCreateWithURL CFURLCreateDataAndPropertiesFromResource failed with error code -11.
–
hbridgeMay 6 '14 at 21:48

I tried both variants in this gist. Both return error -11. Are you sure ALAssetRepresentation URLs work for CGCreateWithURL? If not the provider stuff above seems like the right way to read the assets.
–
hbridgeMay 6 '14 at 23:18