Memory leak drawInRect on iOS5.0.1

2019-02-04 16:18发布

问题:

I have the following code fragment that I use to scale images. This is in a loop that creates and drains an autorelease pool for each pass. This code works fine in the simulator in iOS5.0, in iOS4.3 on iPad or simulator, but on iOS5.0.1 on an iPad1, after 50-60 passes, drawInRect starts consuming memory that never gets released. I had been calling this from a secondary thread, but now invoke the scaling operations on the main thread.

UIGraphicsBeginImageContext( newSize );
[image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

Am I doing something wrong or is this an iOS5.0.1 bug?

Update: I've tried many tests. I have been able to prove that the exact same code compiled with XCode 4.0 runs fine on the same iPad. Same code compiled with XCode 4.2.1 causes an out of memory condition. This scaling routine is being invoked in a background thread. I wrote a different scaling routine using lower level core graphics calls. It doesn't leak with XCode 4.0 but does leak when in my application with XCode 4.2.1. The exact same routine and invocation tree run in a stand alone project does not appear to leak (much) memory on XCode 4.2.1. I'm waiting to hear from Apple on this one. In the mean time I need to use XCode 4. The only install image I have requires Snow Leopard which means I'm using my ancient 5.5 yr old machine. Thanks

Update 1/2012 This only seems to occur if the app is started from within XCode. Same executable started on the iPad does no exhibit the leak. A different app with the same routine does not exhibit the leak.

I've opened a bug report with Apple and have sent them a project which reproduces the problem. I don't expect it to be resolved anytime soon, but it doesn't seem as pervasive as I originally thought.

Update 6/2012 Despite having sent Apple a minimal project which reproduced the problem, they claim not to be able to reproduce the problem and are not making any progress on it.

回答1:

I believe I have FINALLY found the cause of the memory leak. I discovered similar behavior when doing some Core Data inserts. Looping, creating many objects that are released. When run on iPad, memory usage goes up although no leak is evident until the app crashes out of memory. But when initiated from the device, it runs without a problem.

It occurred to me that its something about the way its being started from Xcode. Must be a debug setting in the project.

Turns out the problem was caused by having NSZombieEnabled while debugging. To disable this setting in Xcode 4, right click on the schemes, ie app>targetDevice, edit the scheme, select the Debug action, arguments tab. To enable NSZombieEnabled, an environment variable is created with that name with a value of YES and the variable is enabled. To disable it, uncheck the checkbox.

NSZombieEnabled is used to determine if you attempt to release an object that has already been released. To do this, the environment is keeping track of all released objects. This is consuming memory which appears as a memory leak.

Once I disabled this, my app that used to quickly grow over 115MB before being killed on an iPad1 now happily sits at 24MB with no memory leak.



回答2:

The code you posted shouldn't be causing leaks. The leak is definitely somewhere else.

I would recommend the following two steps:

  1. Post the code you're using to manage the autorelease pool.
  2. Make sure you're executing these lines of codes in the main thread (Apple's documentation indicates that this is in fact important).