Xcode 4.5 - OpenGL glEnable(GL_DEPTH_TEST)EXC_BAD_ACCESS

时间:2013-01-27 20:39:02

标签: opengl xcode4.5 osx-mountain-lion glut

在我尝试学习CG和OpenGL之后,我找到了the book "Interactive Computer Graphics",我觉得这对初学者来说是个不错的选择。现在,我正在尝试按照书中的理论创建3D中所谓的Sierpinski垫片。该项目位于Xcode 4.5中,可以很好地构建并运行,但是当它到达glEnable(GL_DEPTH_TEST)行时,它会崩溃并且Xcode会显示错误Exc_bad_access

以下是我的代码:

//
//  main.cpp
//  SierpinskiGasket
//
//  Created by Federico Martinez on 24.01.13.
//  Copyright (c) 2013 ParallelDev. All rights reserved.
//

#include "Angel.h"

const int NumTimesToSubdivide = 3;
const int NumTriangles = 27;  // 3^5 triangles generated
const int NumVertices  = 3 * NumTriangles;

vec3 points[NumVertices];
vec3 base_colors[4] = {
    vec3(1.0, 0.0, 0.0),
    vec3(0.0, 1.0, 0.0),
    vec3(0.0, 0.0, 1.0),
    vec3(0.0, 0.0, 0.0)
};
vec3 colors[NumVertices];

int Index = 0;
int colorIndex;

//----------------------------------------------------------------------------

void triangle( const vec3& a, const vec3& b, const vec3& c ){
    colors[Index] = base_colors[colorIndex];
    points[Index++] = a;
    colors[Index] = base_colors[colorIndex];
    points[Index++] = b;
    colors[Index] = base_colors[colorIndex];
    points[Index++] = c;
}
//----------------------------------------------------------------------------

void tetra(vec3 a, vec3 b, vec3 c, vec3 d){
    colorIndex = 0;
    triangle(a, b, c);
    colorIndex = 1;
    triangle(a, c, d);
    colorIndex = 2;
    triangle(a, d, b);
    colorIndex = 3;
    triangle(b, d, c);
}
//----------------------------------------------------------------------------

void divide_tetra(const vec3& a, const vec3& b, const vec3& c, const vec3& d, int count){
    if ( count > 0 ) {
        vec3 mid[6];

        mid[0] = (a+b) / 2.0;
        mid[1] = (a+c) / 2.0;
        mid[2] = (a+d) / 2.0;
        mid[3] = (b+c) / 2.0;
        mid[4] = (c+d) / 2.0;
        mid[5] = (b+d) / 2.0;

        divide_tetra(a, mid[0], mid[1], mid[2], count-1);
        divide_tetra(mid[0], b, mid[3], mid[5], count-1);
        divide_tetra(mid[1], mid[3], c, mid[4], count-1);
        divide_tetra(mid[2], mid[5], mid[5], d, count-1);

    }else {
        tetra(a, b, c, d);    // draw tetrahedron at end of recursion
    }
}

//----------------------------------------------------------------------------

void
init( void )
{
    vec3 vertices[4] = {
        vec3(-1.0, -1.0, -1.0),
        vec3(1.0, -1.0, -1.0),
        vec3(0.0, 1.0, -1.0),
        vec3(0.0, 0.0, 1.0)
    };

    // Subdivide the original triangle
    divide_tetra(vertices[0], vertices[1], vertices[2], vertices[3], NumVertices);

    // Create a vertex array object
    GLuint vao;
    glGenVertexArrays( 1, &vao );
    glBindVertexArray( vao );

    // Create and initialize a buffer object
    GLuint buffer;
    glGenBuffers( 1, &buffer );
    glBindBuffer( GL_ARRAY_BUFFER, buffer );

    glBufferData( GL_ARRAY_BUFFER, sizeof(points)+sizeof(colors), NULL, GL_STATIC_DRAW );
    glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(points), points);
    glBufferSubData(GL_ARRAY_BUFFER, sizeof(points), sizeof(colors), colors);

    // Load shaders and use the resulting shader program
    GLuint program = InitShader( "vertex.glsl", "fragment.glsl" );
    glUseProgram( program );

    // Initialize the vertex position attribute from the vertex shader
    GLuint loc = glGetAttribLocation( program, "vPosition" );
    glEnableVertexAttribArray( loc );
    glVertexAttribPointer( loc, 3, GL_FLOAT, GL_FALSE, 0,
                          BUFFER_OFFSET(0) );


    GLuint loc2 = glGetAttribLocation(program, "vColor");
    glEnableVertexAttribArray(loc2);
    glVertexAttribPointer(loc2, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(sizeof(points)));

    glClearColor( 1.0, 1.0, 1.0, 1.0 ); /* white background */
}

void display(){
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glDrawArrays(GL_TRIANGLES, 0, NumVertices);
    glFlush();
}

int main(int argc, char** argv){

    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGBA | GLUT_3_2_CORE_PROFILE | GLUT_DEPTH);
    glEnable(GL_DEPTH_TEST);
    glutInitWindowSize(640, 480);
    glutCreateWindow("Sierpinski Gasket Recursive");

    init();

    glutDisplayFunc(display);

    glutMainLoop();

    return 0;
}

大部分代码来自本书。文件Angel.hInitShader.cpp提供了大多数着色器和矢量实用程序,它们由本书的作者提供。

Exc_bad_access是什么意思?代码中是否有任何可能导致此问题的错误?

更新GDB Stacktrace

(gdb) t a a bt

Thread 5 (process 60424):
#0  0x00007fff8ecce6d6 in __workq_kernreturn ()
#1  0x00007fff8e5fdeec in _pthread_workq_return ()
#2  0x00007fff8e5fdcb3 in _pthread_wqthread ()
#3  0x00007fff8e5e8171 in start_wqthread ()

Thread 4 (process 60424):
#0  0x00007fff8ecce6d6 in __workq_kernreturn ()
#1  0x00007fff8e5fdeec in _pthread_workq_return ()
#2  0x00007fff8e5fdcb3 in _pthread_wqthread ()
#3  0x00007fff8e5e8171 in start_wqthread ()

Thread 3 (process 60424):
#0  0x00007fff8ecce6d6 in __workq_kernreturn ()
#1  0x00007fff8e5fdeec in _pthread_workq_return ()
#2  0x00007fff8e5fdcb3 in _pthread_wqthread ()
#3  0x00007fff8e5e8171 in start_wqthread ()

Thread 2 (process 60424):
#0  0x00007fff8ecced16 in kevent ()
#1  0x00007fff8d6b0dea in _dispatch_mgr_invoke ()
#2  0x00007fff8d6b09ee in _dispatch_mgr_thread ()

Thread 1 (process 60424):
#0  0x00007fff8ecf03d7 in glEnable ()
#1  0x000000010000212a in main (argc=1, argv=0x7fff5fbff800) at /Users/BRabbit27/Documents/COURSERA/ComputerGraphicsBook/SierpinskiGasket3D/SierpinskiGasket3D/main.cpp:129

更新LLDB Stacktrace

(lldb) bt all
* thread #1: tid = 0x2e03, 0x00007fff8ecf03d7 libGL.dylib`glEnable + 15, stop reason = EXC_BAD_ACCESS (code=1, address=0x248)
    frame #0: 0x00007fff8ecf03d7 libGL.dylib`glEnable + 15
    frame #1: 0x000000010000212a SierpinskiGasket3D`main + 58 at main.cpp:129
    frame #2: 0x00007fff8fd5e7e1 libdyld.dylib`start + 1

  thread #2: tid = 0x3103, 0x00007fff8ecced16 libsystem_kernel.dylib`kevent + 10
    frame #0: 0x00007fff8ecced16 libsystem_kernel.dylib`kevent + 10
    frame #1: 0x00007fff8d6b0dea libdispatch.dylib`_dispatch_mgr_invoke + 883
    frame #2: 0x00007fff8d6b09ee libdispatch.dylib`_dispatch_mgr_thread + 54

  thread #3: tid = 0x3203, 0x00007fff8ecce6d6 libsystem_kernel.dylib`__workq_kernreturn + 10
    frame #0: 0x00007fff8ecce6d6 libsystem_kernel.dylib`__workq_kernreturn + 10
    frame #1: 0x00007fff8e5fdeec libsystem_c.dylib`_pthread_workq_return + 25
    frame #2: 0x00007fff8e5fdcb3 libsystem_c.dylib`_pthread_wqthread + 412
    frame #3: 0x00007fff8e5e8171 libsystem_c.dylib`start_wqthread + 13

  thread #4: tid = 0x3303, 0x00007fff8ecce6d6 libsystem_kernel.dylib`__workq_kernreturn + 10
    frame #0: 0x00007fff8ecce6d6 libsystem_kernel.dylib`__workq_kernreturn + 10
    frame #1: 0x00007fff8e5fdeec libsystem_c.dylib`_pthread_workq_return + 25
    frame #2: 0x00007fff8e5fdcb3 libsystem_c.dylib`_pthread_wqthread + 412
    frame #3: 0x00007fff8e5e8171 libsystem_c.dylib`start_wqthread + 13

  thread #5: tid = 0x3403, 0x00007fff8ecce6d6 libsystem_kernel.dylib`__workq_kernreturn + 10
    frame #0: 0x00007fff8ecce6d6 libsystem_kernel.dylib`__workq_kernreturn + 10
    frame #1: 0x00007fff8e5fdeec libsystem_c.dylib`_pthread_workq_return + 25
    frame #2: 0x00007fff8e5fdcb3 libsystem_c.dylib`_pthread_wqthread + 412
    frame #3: 0x00007fff8e5e8171 libsystem_c.dylib`start_wqthread + 13

1 个答案:

答案 0 :(得分:5)

简短回答:在glutCreateWindow之后移动任何OpenGL调用。

基本原理:OpenGL使用一种名为 context 的数据结构,它存储了所有内部状态:纹理,着色器,状态设置等。每个OpenGL函数在启动之前都会访问当前上下文操作。创建上下文是您正在使用的窗口系统的函数,或者在GLUT的情况下,glutCreateWindow函数。 OP中发生的事情是OpenGL实现实际上是解除引用NULL指针并导致异常。

这对于OpenGL实现来说是不好的形式 - 如果没有当前的上下文,大多数实现通常会立即返回任何OpenGL函数。