【问题标题】:Random crash on iPhone OpenGL app when navigating导航时 iPhone OpenGL 应用程序随机崩溃
【发布时间】:2011-05-05 03:37:56
【问题描述】:

我正在开发一个混合 OpenGL ES 和常规 iPhone UI 的 iPhone 应用程序。这意味着有一个EAGLView 向用户致意,然后是一些常规的UIViews 被推到它上面(有一个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 下没有发现泄漏。
  • 在模拟器上没有崩溃,但有时会出现非常明显的延迟。
  • 在崩溃之前,Instruments/OpenGL/ResourceBytes 中有大量已发布的数据。
  • 我同时使用 VBO 和 vertex/texcoord/normals 数组。

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

更新:

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

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

似乎来自layoutSubviewsdeleteFrameBuffer 调用与createFramebuffer 不匹配。

更新 2:

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

现在我该如何解决那个

【问题讨论】:

  • 听起来你可能正在双重释放某些东西......
  • 好吧,我自己并没有释放任何东西。一个视图被推送到我的 OpenGL 视图上,然后弹出,然后在前几次渲染中崩溃。
  • 我想要一个真正的解决方案,它会让我更好地理解 UIKit 与 OpenGL ES 的交互。添加了赏金。
  • 有趣的问题。没有代码,我们很难提供帮助。我认为你是对的,找到根本原因很重要。思路:在draw中间调用deleteFrameBuffer的栈是什么样子的?它在什么线程上?放入一些日志以显示调用各种关键函数时它们所在的线程。
  • 好吧,代码几乎是标准的 OpenGL ES 模板。堆栈很长,在一个线程上。我正忙于其他优先事项(项目截止日期快到了),之后我会尝试发布堆栈跟踪。

标签: iphone objective-c opengl-es crash


【解决方案1】:

我还没有找到“适当”的修复方法,但我添加了一种解决方法。

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)
{
    // ...
}

它似乎没有副作用(如显示损坏等),所以我暂时就这样吧。

【讨论】:

    【解决方案2】:

    这是根据我最近所做的事情的疯狂猜测。

    我所做的是打破加载阶段。我想在加载大量资源时显示进度条 - 这是一个缓慢的过程,所以我想提供一些用户反馈。

    我的第一步类似于 Xcode 提供的 OpenGL ES 示例,因为我在 ES?Renderer 上调用了一个 init。但在那之后我停止了这个过程,所以我可以加载其他资源。

    长话短说,由于我重新安排了代码,[EAGLView layoutSubviews] 在我初始化后从未被调用过。我没有发生崩溃,但在此之后没有发生任何事情。

    我必须做的是,在我完成初始化 OpenGL 的上下文并加载所有数据后,我必须手动调用 [EAGLView layoutSubviews]。这似乎为我解决了问题。

    也许您需要尝试类似的方法。初始化 OpenGL 上下文和数据后,在进入绘图例程之前调用[EAGLView layoutSubviews]。也许这会阻止此调用再次出现在您的渲染步骤中并崩溃。

    【讨论】:

      【解决方案3】:

      在黑暗中刺伤:您的设备内存不足,应用程序收到内存警告,负责 GL 视图的控制器释放视图,这是您没有考虑到的吗?当您取消默认 didReceiveMemoryWarning 时,问题会消失吗?

      - (void) didReceiveMemoryWarning { /* nothing we can do, sorry */ }
      

      …或者您可能正在从另一个没有上下文的线程调用 OpenGL?

      【讨论】:

      • 不是内存警告。我没有使用那么多内存(~5-6 MB),而且我已经验证过了。
      • 我也没有创建任何线程,而且我的上下文在 gdb 中有效。
      • 仅供参考 - 为现代 iOS 应用程序添加多显示器支持,我就是这样。多显示器所需的“额外”内存是巨大的(我所做的只是创建一个 EAGLContext 并显示它),它会将应用程序推到内存限制之上,并且 iOS 没有为第二个视图提供足够的内存来呈现.主视图冻结,应用程序崩溃,Apple 会记录有关 GPU 刚刚崩溃的情况(否 - iOS 内存不足并拒绝分配内存)
      【解决方案4】:

      我遇到了这个问题,并使用了你的工作一段时间。然而,我最近注意到的是,崩溃只发生在方向改变时。

      我将根视图控制器更改为在 WillRotate... 中暂停显示链接并在 DidRotateFrom... 委托函数中恢复它。

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

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

      【讨论】:

      • 有趣!我不再从事那个项目,这是一个快速的 PoC,但我会记住你的解决方案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-07-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-05
      相关资源
      最近更新 更多