Guard Malloc导致wacko应用程序行为

时间:2013-06-06 22:26:14

标签: ios objective-c xcode guard-malloc

我有一个iOS应用程序,我认为内存踩踏正在发生。所以我在Xcode中启用了Guard Malloc,Guard Edges和Scribble并运行它以尝试跟踪它。但是在启用Guard Malloc的情况下,事情开始出现问题的方式非常奇怪。在某些(可预测的)情况下,视图的背景不会被绘制,您可以看到它们背后的视图。如果我进行文件下载,应用程序会在下载结束时在主线程上崩溃,而我的代码中没有任何代码(main除外),并且有时会在控制台中记录一些图形错误:

<Error>: CGBitmapContextInfoCreate: unable to allocate 201000 bytes for bitmap data
<Error>: CGContextSetInterpolationQuality: invalid context 0x0

我的代码中的任何地方都没有使用其中某些内容(例如CGBitmapContextInfoCreate)。

记录的最后一件事是:

Failed to VM allocate 262144 bytes
Explicitly trapping into debugger!!!

有没有其他人使用Guard Malloc导致这类错误?这可能是什么根源?

1 个答案:

答案 0 :(得分:4)

Guard Malloc通过内存管理单元(MMU)工作。 MMU允许您标记内存的某些部分,允许进程访问,某些区域是非法的 - 这实质上是受保护的内存。他们通过将内存划分为单个页面(通常为4kb)并将相关权限归于每个页面来实现此目的。它们无法为每个地址单独存储属性,因为这需要大量存储空间。

MMU会引发非法访问异常。

当运行普通代码时,所有意味着某些越界访问不会引发异常,因为大量数据小于4kb,因此大多数数据与其他数据共享页面。即使不是您打算写入的数组,或者页面已被新对象重用,也可以对页面中的任何位置进行写入。

所以Guard Malloc为每个对象提供一个单独的页面。这会大大增加您的内存占用量,因为它可以将所有对象大小舍入到页面大小。这也是杀死性能的原因 - 任何明智的缓存算法都无法正常运行。

副作用是存储的存储空间要少得多。假设您有NSString通常占用280个字节的存储空间。那么它现在占据整个页面。所以你的内存耗尽更快。 (编辑:根据Greg在下面的评论,一旦分配了一个页面,Guard Malloc不允许它返回到池中,因此你的内存占用量会累积,这意味着你几乎肯定最终会耗尽内存而不管给定[几乎]所有对象都在堆上并返回对象是正常的)

Guard Edge可以通过在每个分配之间放置空页来加剧这种情况。因此,每个分配的对象至少会从虚拟内存池中获取一个额外的页面,否则它将不具备该页面。如果虚拟池的大小足够接近物理池,则会对您产生影响。

当被要求更新其内容时,

CGBitmapContextInfoCreate几乎肯定会被您正在使用的标准UIView内部使用。系统不再具有足够的内存来满足请求,看起来该视图不会尝试优雅地处理该结果。

可能唯一有意义的建议是单独尝试单独的调试工具。