2013-04-26 62 views
1

我有以下代碼,取自我正在開發的OpenGL應用程序的一部分。當調用glfwInit()時,GDB報告代碼立即發生段錯誤。奇怪的是,如果我將height的值更改爲256(或至少如此,則任何事情都會如此),segfault消失。SegForm與GLFW和GLEW

#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的值會影響段錯誤。

編輯:發佈了更多的代碼。段錯誤仍與寬度/高度發生在512,但在256

+1

好吧,'512 * 512 * 3',再乘以3,每個浮點4個字節,爲您提供3145728個字節。或3.14 MB(PI ?!)。這也是唯一的一個數組,你以後也會創建另一個索引數組。你確定你沒有完全消除你的堆棧,可能堆嗎?也就是說,嘗試在堆上動態分配這些數組。應該有點安全。噢,也許檢查GCC的標準堆棧大小(我不使用GCC,所以我不能在那裏幫忙)?我認爲堆棧/堆損壞是一個問題。 – Hydronium 2013-04-26 20:00:38

+0

'4每個浮動4個字節'*完全忘了解決這個問題。 – Hydronium 2013-04-26 20:15:08

+0

@Hydronium:我在調用'glBufferData()'時犯了一個錯誤,但你在堆上分配的建議解決了我的問題。隨意添加一個答案,我會接受它。 – cdk 2013-04-26 23:56:23

回答

2

您最終在堆棧上分配了9437184個字節的數據。 9.43 MB。這是很多內存在一個堆棧幀,並可能超過您的環境允許整個堆棧。

老實說,我不確定精確問題是什麼,但是因爲你提到一個較小的高度值可以修復所有東西(切割高度減半〜4.7MB),我認爲這是問題所在。至少,5MB對於堆棧大小似乎是合理的,雖然我讀過the default for Visual Studio is 1MB。如果你想更深入地瞭解,發現默認堆棧大小GCC給出或明確設置堆棧大小(假設你可以),直到你找到段錯誤。一個快速搜索說它是圍繞8MB,雖然這可能不準確。假設這是正確的,那麼你設法超過了它。

動態地在堆上設置數據。它通常意味着大量數據,而堆棧則用於臨時/本地存儲。

+3

我邀請了解堆棧,堆和GCC之間關係的人員,以擴展此答案。 – Hydronium 2013-04-27 01:00:37

2

運行正常你沒有用數據初始化heightmap

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

如果你想要做的是初始化OpenGL的緩衝區對象是什麼,你可以簡單地傳遞一個空指針。

BTW:所有glBuffer…一直核自從OpenGL的1.4,即你不應該使用ARB擴展,但可以放心地使用核心功能,即使是在最古老的實現,你會發現這幾天(甚至適用於我的老式的基於GeForce2的古董電腦)。