与GLFW和GLEW的Segfault

时间:2013-04-26 18:34:35

标签: c opengl segmentation-fault glew glfw

我有以下代码,取自我正在处理的OpenGL应用程序的一部分。 GDB报告在调用glfwInit()时代码会立即发生段错误。奇怪的是,如果我将height的值更改为256(或至少是height <512),则段错误消失。

#include <GL/glew.h>
#include <GL/glfw.h>

static const size_t width = 512;
static const size_t height = 512;

int main(int argc, char const *argv[])
{
    glfwInit();
    glfwOpenWindow(1080, 720, 8, 8, 8, 0, 32, 0, GLFW_WINDOW);
    glewInit();

    float heightmap[width * height * 3];
    for (size_t i = 0, ix = 0; i < width; i++) {
        for (size_t j = 0; j < height; j++) {
            float noise = 0.0f;
            heightmap[ix++] = (float)i;
            heightmap[ix++] = noise;
            heightmap[ix++] = (float)j;
        }
    }

    const int numIndices = (width - 1) * (height - 1) * 6;timd
    GLuint indices[numIndices];
    for (size_t i = 0, ix = 0; i < width - 1; i++) {
        for (size_t j = 0; j < height - 1; j++) {
            indices[ix++] = (i + 0) + (j + 0) * width;
            indices[ix++] = (i + 1) + (j + 0) * width;
            indices[ix++] = (i + 0) + (j + 1) * width;
            indices[ix++] = (i + 0) + (j + 1) * width;
            indices[ix++] = (i + 1) + (j + 0) * width;
            indices[ix++] = (i + 1) + (j + 1) * width;
        }
    }

    GLuint vbo;
    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, width * height * 3 * sizeof(float), heightmap, GL_STATIC_DRAW);

    GLuint ebo;
    glGenBuffers(1, &ebo);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, numIndices * sizeof(GLuint), indices, GL_STATIC_DRAW);

    do {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glBindBuffer(GL_ARRAY_BUFFER, vbo);
        glEnableVertexAttribArray(0);
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
        glDrawElements(GL_TRIANGLES, numIndices, GL_UNSIGNED_INT, NULL);
        glfwSwapBuffers();
    } while(glfwGetKey(GLFW_KEY_ESC) != GLFW_PRESS);

    glDeleteBuffers(1, &vbo);
    glDeleteBuffers(1, &ebo);

    glfwCloseWindow();
    glfwTerminate();
    return 0;
}

来自GDB的回溯显示

#0  0x00000000004009d7 in main (argc=<error reading variable: Cannot access memory at address 0x7fffff6fe41c>, argv=<error reading variable: Cannot access memory at address 0x7fffff6fe410>) at segfault.c:8

我正在使用gcc -g -o segfault segfault.c -lGL -lGLEW -lglfw进行编译。

我对导致此错误的原因感到难过,我不明白为什么更改height的值会影响段错误。

编辑:发布更多代码。 segfault仍然会出现,宽度/高度为512,但在256处运行正常。

2 个答案:

答案 0 :(得分:3)

您最终会在堆栈上分配9437184个字节的数据。 9.43 MB 。这在一个堆栈帧中是很多内存,并且可能比您的环境允许整个堆栈更多。

说实话我不确定精确问题是什么,但是因为你提到一个较小的高度值修复了所有东西(切割高度减半给了4.7 MB)我认为这是问题。至少,5MB似乎对于堆栈大小来说是合理的,尽管我读过the default for Visual Studio is 1MB。如果您想深入了解这一点,请发现GCC提供的默认堆栈大小或显式设置堆栈大小(假设您可以),直到找到段错误。快速搜索说它在8MB附近,虽然这对您来说可能不准确。假设这是正确的,那么你设法超过它。

动态地在堆上设置该数据。它通常用于大量数据,而堆栈则用于临时/本地存储。

答案 1 :(得分:2)

您未使用数据初始化heightmap

float heightmap[width * height * 3];
/* ... */
glBufferDataARB(GL_ARRAY_BUFFER, sizeof(heightmap), heightmap, GL_STATIC_DRAW);

如果你要做的就是初始化OpenGL Buffer Object,你可以简单地传递一个空指针。

BTW:自从OpenGL-1.4以来,所有glBuffer…都已成为核心,即你不应该使用ARB扩展,但可以安全地使用核心功能,即使是在你找到的最老的实现上也是如此这些天(它甚至适用于我的旧GeForce2古董电脑)。