我有一个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导致了这种错误?这一切的根源是什么呢?
发布于 2013-06-07 07:06:05
Guard Malloc通过内存管理单元(MMU)工作。MMU允许您将内存的某些部分标记为允许进程访问,并将某些区域标记为非法-这在本质上就是受保护的内存。它们通过将内存划分为单独的页(通常为4kb )并将相关权限分配给每个页来实现这一点。它们不能为每个地址单独存储属性,因为这需要大量的存储空间。
是MMU引发了非法访问异常。
在运行正常代码时,这意味着一些越界访问不会引发异常,因为您的许多数据小于4kb,因此大多数数据与其他数据共享页面。而且,即使不是要写入的数组,或者新对象已经重用了该页,也可以对页中的任何位置执行写操作。
因此Guard Malloc为每个对象提供了一个单独的页面。这会极大地增加内存占用,因为它会将所有对象大小向上舍入到页面大小。这也是导致性能下降的原因--任何合理的缓存算法都无法正常工作。
一个副作用是可供使用的存储空间要少得多。假设您有一个通常占用280字节存储空间的NSString
。现在它占据了整个页面。所以你会更快地耗尽内存。(编辑:根据Greg下面的评论,一旦一个页面被分配,Guard Malloc就不允许它回到池中,所以你的内存占用是累积的,这意味着你几乎肯定最终会耗尽内存,不管几乎所有的对象都在堆上,返回对象是正常的)
保护边缘可能会加剧这种情况,因为在每次分配之间都会放置空页。因此,分配的每个对象至少会占用虚拟内存池中的一个额外页面,否则就不会有这些页面。如果虚拟池的大小足够接近您的物理池,这可能会影响您。
当被要求更新其内容时,您所使用的某个标准UIView
几乎肯定会在内部使用CGBitmapContextInfoCreate
。系统不再有足够的内存来满足请求,并且视图看起来不会尝试优雅地处理结果。
可能唯一有意义的建议是单独地尝试调试工具。
https://stackoverflow.com/questions/16973263
复制相似问题