我正在开发一个混合OpenGL ES和常规iPhone UI的iPhone应用程序。这意味着有一个EAGLView
问候用户,然后一些常规UIView
被推到它上面(有一个UINavigationController
作为根控制器。)
从子视图导航时,我有一个随机(但非常频繁)的崩溃。这是一个(...审查的......)堆栈跟踪,来自Release版本,但它在Debug中崩溃了。
#0 0x006863d0 in GetFBOBuffers ()
#1 0x00660120 in TerminateScene ()
#2 0x00660314 in FlushScene ()
#3 0x00660cd4 in FlushHW ()
#4 0x0066a6a0 in GLESPresentView ()
#5 0x323533a4 in -[EAGLContext presentRenderbuffer:] ()
#6 0x000026c0 in -[EAGLView presentFramebuffer] (self=0x11ce60, _cmd=<value temporarily unavailable, due to optimizations>) at (...)/Classes/EAGLView.m:157
#7 0x00004fdc in -[(...)ViewController drawFrame] (self=<value temporarily unavailable, due to optimizations>, _cmd=<value temporarily unavailable, due to optimizations>) at (...) ViewController.m:380
#8 0x336ebd9a in __NSFireTimer ()
#9 0x323f54c2 in CFRunLoopRunSpecific ()
#10 0x323f4c1e in CFRunLoopRunInMode ()
#11 0x335051c8 in GSEventRunModal ()
#12 0x324a6c30 in -[UIApplication _run] ()
#13 0x324a5230 in UIApplicationMain ()
#14 0x0000214c in main (argc=1, argv=0x2ffff568) at (...)/main.m:14
以下是我所知道的事项清单:
所以我知道它必须是某种被释放或销毁的数据,但我不知道如何找到它。任何提示和技巧将不胜感激; - )
更新:
设置了一些断点,沿着堆栈移动,查看各种变量,我找到了崩溃的原因,但还没有找到源。
在EAGLView中,在方法presentFramebuffer
发生崩溃的地方和时间,如果我可以相信gdb,则colorRenderBuffer ivar为0,即使尝试断点时它似乎不起作用。
来自deleteFrameBuffer
的{{1}}来电似乎与layoutSubviews
不匹配。
更新2:
以后有很多断点......我发现了一个错误的情况:createFramebuffer
在[EAGLView layoutSubviews]
的中间被称为!因此缓冲区在使用时会被删除... BAM!
现在我该如何修复那个?
答案 0 :(得分:3)
我还没有找到“正确”的解决方案,但我添加了一个解决方法。
在presentFramebuffer
中,我在渲染周围设置了一个布尔值:
if (context)
{
isRendering_PATCH_VARIABLE = YES;
[EAGLContext setCurrentContext:context];
glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer);
success = [context presentRenderbuffer:GL_RENDERBUFFER_OES];
glBindRenderbufferOES(GL_RENDERBUFFER_OES, 0);
isRendering_PATCH_VARIABLE = NO;
}
并在deleteFramebuffer
中,我检查了这个布尔值:
if (isRendering_PATCH_VARIABLE)
{
NSLog(@"GOTCHA - CRASH AVOIDED");
}
if (context && !isRendering_PATCH_VARIABLE)
{
// ...
}
它似乎没有副作用(比如破坏显示等),所以我暂时不会这样做。
答案 1 :(得分:3)
根据我最近做的事情,这是一个疯狂的猜测。
我所做的是打破装载阶段。当我加载了大量资源时,我想显示一个进度条 - 这是一个缓慢的过程,所以我想提供一些用户反馈。
我的第一步类似于Xcode提供的OpenGL ES示例,我在ES?Renderer上调用了一个init。但在那之后我停止了这个过程,所以我可以加载其他资源。
简而言之,由于我重新安排了代码,[EAGLView layoutSubviews]
在初始化后从未被调用过。我没有遇到崩溃,但在此之后没有发生任何事情。
我必须要做的是,在我完成初始化OpenGL的上下文并加载我的所有数据后,我不得不手动调用[EAGLView layoutSubviews]
。这似乎解决了我的问题。
也许你需要尝试类似的东西。初始化OpenGL上下文和数据后,在进入绘图例程之前调用[EAGLView layoutSubviews]
。也许这会停止此调用再次出现在渲染步骤中并崩溃。
答案 2 :(得分:1)
在黑暗中刺伤:您的设备内存不足,应用程序收到内存警告,负责GL视图的控制器释放视图,这是您不计算的内容?禁止默认didReceiveMemoryWarning
时,问题是否会消失?
- (void) didReceiveMemoryWarning { /* nothing we can do, sorry */ }
...或者你是从另一个没有上下文的线程调用OpenGL的?
答案 3 :(得分:1)
我遇到了这个问题并且使用了你的工作一段时间。然而,我最近注意到的是,崩溃只发生在方向改变上。
我更改了我的根视图控制器以暂停WillRotate中的displaylink ...并在DidRotateFrom ...委托函数中恢复它。
这解决了问题,我不再需要黑客工作了。
不幸的是,听起来你的问题略有不同,但我想发布这个以防万一。