iOS5.0.1上的内存泄漏drawInRect

时间:2022-08-17 08:58:36

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.

我有以下用于缩放图像的代码片段。这是一个循环,为每次传递创建和排出自动释放池。此代码在iOS5.0中的模拟器,iPad或模拟器上的iOS4.3中工作正常,但在iPad1上的iOS5.0.1上,经过50-60次传递后,drawInRect开始消耗永不释放的内存。我一直在从辅助线程调用它,但现在调用主线程上的缩放操作。

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?

我做错了什么或者这是一个iOS5.0.1错误?

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

更新:我尝试了很多测试。我已经能够证明使用XCode 4.0编译的完全相同的代码在同一台iPad上运行良好。使用XCode 4.2.1编译的相同代码会导致内存不足。在后台线程中调用此缩放例程。我使用较低级别的核心图形调用编写了不同的缩放程序。它不会随XCode 4.0泄漏,但在我的应用程序中使用XCode 4.2.1时会泄漏。在独立项目中运行的完全相同的例程和调用树似乎不会泄漏(很多)XCode 4.2.1上的内存。我正等着苹果听到这个。同时我需要使用XCode 4.我唯一的安装映像需要Snow Leopard,这意味着我正在使用我古老的5.5岁的机器。谢谢

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.

Update 1/2012仅当应用程序从XCode内启动时才会出现这种情况。在iPad上启动的相同可执行文件没有出现泄漏。具有相同例程的不同应用程序不会出现泄漏。

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.

我已经向Apple发布了一个错误报告,并向他们发送了一个再现问题的项目。我不认为它会很快得到解决,但它似乎并不像我原先想象的那样普遍。

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.

更新6/2012尽管已经向Apple发送了一个复制问题的最小项目,但他们声称无法重现问题并且没有取得任何进展。

2 个解决方案

#1


4  

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.

我相信我最终找到了内存泄漏的原因。我在做一些Core Data插入时发现了类似的行为。循环,创建许多已发布的对象。在iPad上运行时,内存使用量会增加,但在应用程序崩溃内存之前不会出现任何泄漏。但是当从设备启动时,它运行没有问题。

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

我想到了它从Xcode开始的方式。必须是项目中的调试设置。

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引起的。要在Xcode 4中禁用此设置,请右键单击方案,即app> targetDevice,编辑方案,选择Debug操作,参数选项卡。要启用NSZombieEnabled,将使用该名称创建一个环境变量,其值为YES,并且该变量已启用。要禁用它,请取消选中该复选框。

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.

NSZombieEnabled用于确定您是否尝试释放已释放的对象。为此,环境将跟踪所有已释放的对象。这是消耗内存,显示为内存泄漏。

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.

一旦我禁用了这个,我的应用程序曾经快速增长超过115MB,然后在iPad1上被杀死现在高兴地坐在24MB没有内存泄漏。

#2


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. 发布您用于管理自动释放池的代码。
  3. Make sure you're executing these lines of codes in the main thread (Apple's documentation indicates that this is in fact important).
  4. 确保在主线程中执行这些代码行(Apple的文档表明这实际上很重要)。

#1


4  

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.

我相信我最终找到了内存泄漏的原因。我在做一些Core Data插入时发现了类似的行为。循环,创建许多已发布的对象。在iPad上运行时,内存使用量会增加,但在应用程序崩溃内存之前不会出现任何泄漏。但是当从设备启动时,它运行没有问题。

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

我想到了它从Xcode开始的方式。必须是项目中的调试设置。

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引起的。要在Xcode 4中禁用此设置,请右键单击方案,即app> targetDevice,编辑方案,选择Debug操作,参数选项卡。要启用NSZombieEnabled,将使用该名称创建一个环境变量,其值为YES,并且该变量已启用。要禁用它,请取消选中该复选框。

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.

NSZombieEnabled用于确定您是否尝试释放已释放的对象。为此,环境将跟踪所有已释放的对象。这是消耗内存,显示为内存泄漏。

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.

一旦我禁用了这个,我的应用程序曾经快速增长超过115MB,然后在iPad1上被杀死现在高兴地坐在24MB没有内存泄漏。

#2


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. 发布您用于管理自动释放池的代码。
  3. Make sure you're executing these lines of codes in the main thread (Apple's documentation indicates that this is in fact important).
  4. 确保在主线程中执行这些代码行(Apple的文档表明这实际上很重要)。