glShaderSource中的Segfault

HSc*_*ale 2 c++ opengl pointers

好吧,我已经加载了一个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);
}
Run Code Online (Sandbox Code Playgroud)

Ret*_*adi 6

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

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

    char s[] = "abc";
    
    Run Code Online (Sandbox Code Playgroud)

    以下两个表达式:

    &s
    &s[0]
    
    Run Code Online (Sandbox Code Playgroud)

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

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

    char s[] = "abc";
    char* t = s;
    
    Run Code Online (Sandbox Code Playgroud)

    以下两个表达式:

    &t
    &t[0]
    
    Run Code Online (Sandbox Code Playgroud)

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

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

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

const GLchar* vertex_glsl_ptr = vertex_glsl;
glShaderSource(vertexShader, 1, &vertex_glsl_ptr, NULL);
Run Code Online (Sandbox Code Playgroud)

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