glShaderSource中的Segfault

时间:2015-09-10 23:04:34

标签: c++ pointers opengl

好吧我已经加载了glVertex着色器,作为来自hexdump的const char字符串。但是我从下面的代码中得到了一个编译器错误,我无法弄清楚为什么它拒绝编译它,错误是:

   main.cpp: In function ‘void loadShaders()’:
main.cpp:27:55: error: cannot convert ‘const char (*)[92]’ to ‘const GLchar** {aka const char**}’ in argument passing
     glShaderSource(vertexShader, 1, &vertex_glsl, NULL);                                                           ^

但是当我通过将&vertex_glsl强制转换为(const char**)来覆盖错误时,它将在运行时编译但是段错误。为什么会出现这种错误?

const char vertex_glsl[] = {
  0x23, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x31, 0x35, 0x30,
  0x0a, 0x0a, 0x69, 0x6e, 0x20, 0x76, 0x65, 0x63, 0x32, 0x20, 0x70, 0x6f,
  0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3b, 0x0a, 0x0a, 0x76, 0x6f, 0x69,
  0x64, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x28, 0x29, 0x7b, 0x0a, 0x20, 0x20,
  0x20, 0x20, 0x67, 0x6c, 0x5f, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f,
  0x6e, 0x20, 0x3d, 0x20, 0x76, 0x65, 0x63, 0x34, 0x28, 0x70, 0x6f, 0x73,
  0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x30, 0x2e, 0x30, 0x2c, 0x20,
  0x31, 0x2e, 0x30, 0x29, 0x3b, 0x0a, 0x7d, 0x00
};
const int vertex_glsl_len = 92;

void loadShaders(){
    GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);

    // here's where it segfaults
    glShaderSource(vertexShader, 1, &vertex_glsl, NULL);
    glCompileShader(vertexShader);
}

2 个答案:

答案 0 :(得分:5)

虽然C / C ++指针和数组在许多上下文中的行为方式相同,但它们相同。你在这里偶然发现了什么,包括初始编译错误和添加类型转换后的崩溃,是两者不同的一个例子:

  • 应用于数组的&运算符为您提供数组的地址,该地址是指向存储在数组中的数据的指针。应用运算符产生的实际地址(但不是类型)与数组中第一个元素的地址相同。所以声明:

    char s[] = "abc";
    

    以下两个表达式:

    &s
    &s[0]
    

    导致相同的地址。同样,两个表达式的类型不同,第一个是指向数组的指针,第二个是指向字符的指针,但地址是相同的。

  • 应用于指针变量的&运算符为您提供指针变量的地址。跟进相同的例子:

    char s[] = "abc";
    char* t = s;
    

    以下两个表达式:

    &t
    &t[0]
    

    导致不同的地址。第一个是指针变量t的地址,而第二个是指向第一个字符的指针,与上面的&s[0]相同。

glShaderSource()的第三个参数的类型是const GLchar**,这意味着来传递指针变量的地址。您在第一次尝试时遇到的编译错误是一个严重错误,因为您确实传递了错误类型的值(指向数组的指针)。添加类型转换只是让破坏的代码通过编译器,并在运行时引起崩溃。

要使其工作,您需要将字符串分配给const GLchar*类型的变量,并传递该变量的地址:

const GLchar* vertex_glsl_ptr = vertex_glsl;
glShaderSource(vertexShader, 1, &vertex_glsl_ptr, NULL);

现在可以在没有类型转换的情况下进行编译,并且在运行时不会崩溃。

答案 1 :(得分:0)

<强>尝试:

glShaderSource(vertexShader, 1, &vertex_glsl, &vertex_glsl_len);

问题可能只是在这种情况下它不应该由空终止字符串驱动,而是由大小定义的字符串驱动。

您的char数组终止每行的字符串