导航时在iPhone OpenGL应用程序上随机崩溃

时间:2010-11-04 15:49:48

标签: iphone objective-c opengl-es crash

我正在开发一个混合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

以下是我所知道的事项清单:

  • 我的应用没有收到内存警告。
  • 我的应用程序在仪器下没有发现泄漏。
  • 模拟器没有崩溃,但有时会出现非常明显的延迟。
  • 在崩溃之前,Instruments / OpenGL / ResourceBytes中有大量已发布的数据。
  • 我正在使用VBO和vertex / texcoord / normals数组。

所以我知道它必须是某种被释放或销毁的数据,但我不知道如何找到它。任何提示和技巧将不胜感激; - )

更新:

设置了一些断点,沿着堆栈移动,查看各种变量,我找到了崩溃的原因,但还没有找到源。

在EAGLView中,在方法presentFramebuffer发生崩溃的地方和时间,如果我可以相信gdb,则colorRenderBuffer ivar为0,即使尝试断点时它似乎不起作用。

来自deleteFrameBuffer的{​​{1}}来电似乎与layoutSubviews不匹配。

更新2:

以后有很多断点......我发现了一个错误的情况:createFramebuffer[EAGLView layoutSubviews] 的中间被称为!因此缓冲区在使用时会被删除... BAM!

现在我该如何修复那个

4 个答案:

答案 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 ...委托函数中恢复它。

这解决了问题,我不再需要黑客工作了。

不幸的是,听起来你的问题略有不同,但我想发布这个以防万一。