iOS或MonoTouch中的内存泄漏问题?

4
我们正在对一款iPad应用程序进行内存泄漏的解决,而这个应用程序必须保持足够稳定以便能够24小时不间断地运行,因此,内存泄漏是无法容忍的。
作为一个简单的测试,我们使用“Single View”模板创建了一个新的iPad MonoTouch项目,并在iPad本身上使用Instruments执行它(第三代iPad,没有其他应用程序在运行/内存中)。
在Instruments中,如果我们时常点击“Mark Memory”按钮,它会不断地消耗内存。每次消耗不多,但是总体上还是会有所增加:
该应用程序实际上并没有执行任何操作,但显然有某些操作在分配内存。
这是iOS问题、MonoTouch问题还是其他问题?
创建一款24/7的iPad应用程序是否现实?我们担心当我们开始添加代码时,内存泄漏的数量也会增加。这个应用程序可以在以上图像的泄漏情况下运行相当长的时间,但是如果泄漏量增加,内存满的截止日期将更快到来。

这些框架都存在微小的泄漏。 - Carl Veazey
@Carl:有任何参考资料吗,还是只是猜测? - ctacke
@ctacke 没有参考,只是我通过分析发现的。 - Carl Veazey
1个回答

6
这些截图显示的是分配情况,而非内存泄漏。您可以要求Instruments跟踪泄漏,即找到未发现分配内存的引用的位置。
但是,如果没有更多数据,就无法确定它们是否正常。我们至少需要知道分配来自哪里?Instruments可以告诉您有关每个分配的更多详细信息。尝试在每个堆快照下钻取树以查看分配来自何处。
类似的情况通常是由缓存引起的,这在每个级别都会发生。在应用程序代码之外,您会注意到iOS及其框架正在进行缓存(例如图像、webkit等)。
Mono本身也进行缓存,并使用在需要时会增长的内存池。分配(即使已释放)也将显示出来,但这不是泄漏——当释放时,如果可能(例如大小),则会重复使用内存。
当然,这也可能是一个错误(在应用程序、任何框架、单触摸、iOS中)。给定时间,如果在错误的地方发生(例如运行循环的一部分、处理通知...),一个单独的小泄漏就足以使应用程序崩溃。只有找到分配来自何处以及它们是否重复分配(来自同一来源)才能告诉您这些分配的重要性。

编辑(更多内容)

昨晚我对自己的应用程序进行了一次实验。下面的截图显示了13小时45分钟内堆增长的情况。

Heap Growth over 13h45m

在前4小时(1-13)中,应用程序处于前台。最后一部分(14)应用程序处于后台(晚上屏幕关闭)。录音也在#14之后停止,因此该数字没有机会随着时间的推移而下降。
我的应用程序更大(初始基线为5MB),启动后我没有使用它。一旦我知道初始化完成(它正在加载一个{{link1:相当大}}的80MB数据库),我进行了第一次“标记堆”。另一方面,也{{link2:侦听网络事件}},使用NSNetServiceBrowser,回调到托管代码中(没有任何视觉提示)。
扩展Heapshot#1显示一个单个对象,48字节,带有以_ZL13_cache_mallocmcache_filllookupMethod_class_lookupMethodAndLoadCache3结尾的堆栈跟踪...在调用者中没有显示我的应用程序或mono。
扩展Heapshot #2显示四个对象,前两个在它们的堆栈跟踪中带有CA :: Render :: Encoder :: ObjectCacche :: invalidate(...)CGNotificationCenterPostNotification。第三个是_cache_addForwardEntry,第四个看起来像Heapshot #1,但与第3个一样,它来自_XReceivedStatusBarDataAndAction(不是由我的应用程序或monotouch直接执行的操作)。
扩展Heapshot #3显示10个对象...有点长,无法列出它们,但它们都在同一个_XReceivedStatusBarDataAndAction调用下。
扩展heapshot #4时也是相同的模式。
Heapshot #5有一个区别(11个中的一个),其中分配来自于一个派发队列(_xpc_connection_init),但没有管理(应用程序)或mono [touch]堆栈帧可见。
扩展Heapshot #6、#7、#8时与#3相同的模式。
Heapshot #9为空(没有分配)。
Heapshot #10、#11与#3相同。
Heapshot #12也是空的。
Heapshot #13和#3大部分相似,但它也缓存了一些图像,CA::Render::Image::caches_encoding()以及另一个_cache_fill+lookUpMethod在收到_significantTimeChange通知时发生(未被管理或MT堆栈帧在UIApplicationMain下方)。还有一些其他的分配与通知相关。

Heapshot #14大多是关于通知(可能是告诉它正在进入后台)。还有一些_cache_fill分配。

这是iOS问题、MonoTouch问题还是其他问题?

没有任何东西指向MonoTouch甚至我的应用程序。另一方面,我没有将其与ObjC应用程序进行比较(可能没有时间这样做),但我相信您会看到非常接近的东西-取决于使用哪个API/服务(执行相同操作的应用程序应显示相同的分配)。

正如我之前所说,泄漏(或意外的内存保留)通常是特定于API的。如果您在工具中发现奇怪的堆栈跟踪,请填写错误报告(根据堆栈跟踪填写给Xamarin或Apple),以便对它们进行分析和修复(如果有bug的话)。

创建一款全天候的iPad应用程序的计划是否现实?

关于24/7运行应用程序,我认为这是可行的 - 但需要用户的合作(这可能是不现实的)。切换到另一个应用程序(主页按钮,手势)意味着您的应用程序不会在前台,苹果可以关闭任何后台应用程序以回收内存。例如,App X用尽了内存,iOS开始请求并杀死后台应用程序以满足前台应用程序。


从iOS 6开始,“引导访问”(http://www.apple.com/ios/whats-new/#accessibility)允许禁用硬件按钮,这使得iPad对于终端/信息亭架更加有趣。因此,全天候运行iOS应用程序不再那么不可思议了。 :) - Andreas Ley

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接