jme*_*fin 1 c++ opengl shader segmentation-fault
char buffer[1024];
memset(buffer, 0, sizeof(buffer));
FILE *vertexShaderFile = fopen(vertexShaderPath.c_str(), "rb");
fread(buffer, 1, sizeof(buffer) - 1, vertexShaderFile);
fclose(vertexShaderFile);
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, (const char **)&buffer, nullptr);
glCompileShader(vertexShader);
Run Code Online (Sandbox Code Playgroud)
使用此代码,我在调用 时遇到分段错误glShaderSource()。使用 GDB,我已经确认(着色器代码)的内容buffer正确地以 null 终止。最重要的是,我检查了 和GLEW_ARB_shader_objects都已glShaderSource加载。
这里可能发生了什么?
buffer经过一番修补后,我发现如果我在堆上制作一个副本,即通过std::string从中制作 a 并将glShaderSource()指针传递给其返回的指针c_str(),它就可以工作。
现在我更困惑了。
最重要的是,即使我只是声明一个char *指向buffer并将其传递进去,它也能工作。当您声明指向数组的指针与声明指向指针的指针时,C++11 是否做了一些特殊的事情?
您错误地使用了 C 语法:
char buffer[1024];
...
glShaderSource(..., (const char **)&buffer, ...);
Run Code Online (Sandbox Code Playgroud)
这不是指向真实字符串数据的指针。根据定义,与此处&buffer相同- 指向中第一个类型 的buffer指针。将其转换为其他内容只会隐藏此处的错误。charbufferchar *
这种结构原则上是行不通的。没有显式变量保存该缓冲区的地址,编译器将buffer在编译时直接转换对内存位置(在本例中为堆栈上)的访问。与常见的误解相反,数组与C/C++ 中的指针不同。数组的名称只是计算为指向第一个对象的指针值,但这不是同一件事。您要做的事情在概念上与获取立即值的地址相同:&12345。你永远无法获得本来就不存在的东西的地址。
您当然可以做的是创建一个:
char buffer[1024];
char *pBuffer=buffer;
...
glShaderSource(..., &pBuffer, ...);
Run Code Online (Sandbox Code Playgroud)
现在,内存中有一个指针,它实际上保存了缓冲区的地址。当然,您可以获取该指针变量的地址,获取具有char **类型的表达式。