gldrawarraysがexc_bad_accessでクラッシュしました
質問
Caeacleglayerを使用してUIViewをそのレイヤーとして使用するiPhoneアプリケーションを書いています。すべてが大丈夫で、1つの小さな問題から離れています: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分間の回転装置が必要です。
私はそれがクラッシュする場所からCaeagllayの初期化/フレームの変更に関連するミスを犯していると思います(私は信じています)。
そのため、init and Layoutサブビューのメソッドは次のとおりです。
init:
...
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_MODELVIELとGL_POJECTION MATRICTSのみを設定しますので、そこに悪いことがないと思います。
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];
.
このバグの原因を見つけることができる方法については、リストされているコードや提案についてのコメントを感謝します。
解決
は、DrawAraRyaysに渡されているtotalPoints
変数が疑われる、あるいはそれらの配列が静的ではない場合は、vertexcorrdinatesまたはTextureCoordinatesの値を使用することができます。クラッシュは、アレイを描いている間、メモリの終わりを降りていることを意味します。私はあなたのGLの設定やあなたのメモリ管理についてもっと心配していません、そしてあなたが回転中に違うものを描いているのです。
(FWIW、レンダーバッファにバインドするたびにRenderBufferStorageを呼び出す必要があるとは思わない。あなたがそれらを作成するときだけそれをする必要があるだけです。サイズを変更したときに実際にバッファを破棄しないでください。ただし最初からそれらを再作成してください。)