好吧我已经加载了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);
}
答案 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数组终止每行的字符串。