ios - 调用 glDrawArrays 时随机崩溃

标签 ios opengl-es exc-bad-access

我正在制作一个 iOS 应用程序,它可以渲染大量纹理,我可以即时从磁盘流式传输这些纹理。我使用 NSCache 来进行纹理的 LRU 缓存。一个屏幕上有 3D 模型,另一个屏幕上有全屏纹理细节,可以通过滑动来更改该纹理。一种非常简单的轮播。该应用程序在 1GiB 设备上永远不会占用超过 250MiB 的 RAM,纹理的缓存效果很好。

对于全屏 View ,我有一个基于屏幕分辨率和纹理分辨率(不同纹理坐标)的 VBO 缓存。我从不删除这些 VBO,并且总是检查 VBO 是否正常 (glIsBuffer())。屏幕是单独的 UIViewController,我在它们中使用相同的 EAGLContext,没有上下文共享。这是可以的,因为它在同一个线程上。

这一切都是 Open GL ES 2.0,一切都运行良好。我可以在 3D/2D 屏幕之间切换,更改纹理。根据可用内存的需要,纹理会动态创建/删除。

但有时我在调用时渲染全屏四边形时会随机崩溃:

glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

当我连续收到大量内存警告时,可能会发生这种情况。有时我可以在几秒钟内收到数百个内存警告,并且应用程序运行正常,但有时它会在滑动到新的全屏纹理四边形时崩溃。即使对于已经全屏渲染的纹理也会发生这种情况。它在使用相同纹理的 3D 模型上永远不会崩溃。

崩溃报告始终位于 glDrawArrays 调用中(在我的代码中),并在 0x00000018 处出现 EXC_BAD_ACCESS KERN_INVALID_ADDRESS 异常。堆栈跟踪中的最后一个调用始终是gleRunVertexSubmitARM。这种情况发生在各种 iPad 和 iPhone 上。

看起来系统内存压力损坏了一些 GL 内存,但我不知道何时、何地以及为什么。

我还尝试从 VBO 切换到在堆上保存顶点数据的旧方式,在调用 glDrawArrays 之前,我首先检查顶点数据是否不为 NULL 。结果是一样的,在内存不足的情况下随机崩溃。

有什么想法可能是错误的吗? EXC_BAD_ACCESS中的地址0x00000018确实很糟糕,但我不知道它应该是谁的地址。取消分配的纹理或着色器是否会导致 glDrawArrays 中出现 EXC_BAD_ACCESS

最佳答案

经过几天的深入调试,我终于弄清楚了。问题在于 NSCache 存储 OpenGL 纹理。在内存压力下,NSCache 开始从中删除项目以释放​​内存。问题是,在这种情况下,它在自己的后台线程(com.apple.root.utility-qos)上执行此操作,因此该线程没有 GL 上下文(并且没有与主上下文的共享组),因此纹理名称为不是有效的名称(无法删除)并且会泄漏 GL 内存。因此,在出现一些内存警告之后,出现了大量泄漏的 GL 纹理、内存已满,应用程序最终崩溃了。

TL DR: 不要使用 NSCache 来缓存 OpenGL 对象,因为它会在内存警告后泄漏它们。

关于ios - 调用 glDrawArrays 时随机崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32123339/

相关文章:

opengl-es - SSAO 文物分为三部分

java - OpenGL ES 2.0 - 渲染深度缓冲区

ipad - 顶点着色器中的纹理查找在 iPad 设备和 iPad 模拟器上的行为不同 - OpenGL ES 2.0

iOS:在 NSThread 中运行计时器导致 EXC_BAD_ACCESS?

ios - 线程 1 : EXC_BAD_ACCESS (code=2, 地址=0x7fff522f9e98)

iphone - 通话结束后重新打开应用程序

ios - GKTurnBasedMatch 不会前进到下一个玩家

ios - 在 xcode 7.x 中安装 cocoapods (pod install) 后断点不起作用

ios - 将 UITextView 高度设置为可变行数

c - C 代码行在完全不相关的代码行上导致段错误