glDrawArrays崩溃,提示EXC_BAD_ACCESS错误。

3

我正在编写一个iPhone应用程序,它使用UIView作为其层,并使用CAEAGLayer作为其图层。一切都很好,工作正常,除了一个小问题:有时会崩溃并显示EXC_BAD_ACCESS错误,以下是堆栈跟踪:

    [EAGLView draw]
    glDrawArrays_Exec
    PrepareToDraw
    DrawFramebufferMakeResident
    AttachmentMakeResident
    TextureMakeResident
    memmove

在这一行代码处,系统崩溃了:

    glVertexPointer(3, GL_FLOAT, 0, vertexCoordinates);
    glTexCoordPointer(2, GL_FLOAT, 0, textureCoordinates);
    glBindTexture(GL_TEXTURE_2D, textures[kActiveSideLeft]);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, totalPoints); //<--Crash here

应用程序仅在界面旋转更改期间崩溃(这也是视图框架更改的唯一情况)。它不经常崩溃; 大多数情况下需要旋转设备3-5分钟才能重现此问题。
我认为我犯了一个错误,与CAEAGLLayer初始化/框架更改有关,因为那是它崩溃的地方(我认为)。
因此,这里是init和layout subviews方法:

    ...
    CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;     
    eaglLayer.opaque = TRUE;

    context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
    if (!context || ![EAGLContext setCurrentContext:context])
    {
        [self release];
        return nil;
    }

    glGenFramebuffersOES(1, &defaultFramebuffer);
    glGenRenderbuffersOES(1, &colorRenderbuffer);
    glGenRenderbuffersOES(1, &depthRenderbuffer);
    glBindFramebufferOES(GL_FRAMEBUFFER_OES, defaultFramebuffer);
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer);
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
    glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, colorRenderbuffer);
    glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
    ...

在设置帧时,我只设置了GL_MODELVIEW和GL_POJECTION矩阵,因此我想那里不会发生什么问题。
LayoutSubviews:

    - (void)layoutSubviews
    {
      [EAGLContext setCurrentContext:context];

        glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer);
        [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer];
        glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
        glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
        glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
        glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES, backingWidth, backingHeight);

        NSAssert1(glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) == GL_FRAMEBUFFER_COMPLETE_OES, @"Failed to make complete framebuffer object: %X", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES));
    }

绘制方法本身看起来像:

        if ([EAGLContext currentContext] != context) {
            [EAGLContext setCurrentContext:context];
        }

        glBindFramebufferOES(GL_FRAMEBUFFER_OES, defaultFramebuffer);
        glViewport(0, 0, backingWidth, backingHeight);

        ...//drawing different triangle strips here

        glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer);
        [context presentRenderbuffer:GL_RENDERBUFFER_OES];

我希望您能就以下代码提出任何意见或建议,以及如何找出此错误的原因。

1个回答

3
我会怀疑传递到drawArrays的totalPoints变量,或者你的vertexCoordinates或textureCoordinates的值是否不是静态的。你的崩溃意味着在绘制数组时你超出了内存的末尾。我对你的GL设置不太怀疑,更关注你的内存管理以及在旋转期间绘制的内容有何不同。
(此外,顺便说一句,我认为你不应该每次绑定渲染缓冲区时都调用RenderBufferStorage。你只需要在创建它们时执行一次即可。话虽如此,我不确定当你改变它们的大小时是否不应该实际上销毁缓冲区并从头开始重新创建它们。)

所有的数组都是静态的(至少它们的大小从不改变),而totalPoints只是一个 #define 常量。 无论如何,我最终决定每次设备旋转时重新创建OpenGL视图,这解决了问题。 我不确定这是否是解决问题的好方法,但至少它能正常工作 =) - Alexey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接