Reputation: 911
I'm creating functions to load shaders, to create meshes, and the like, thus I started a simple program to test the functionalities I was adding, one by one, and I found a problem with this bit:
const char* vertexShader = prm.LoadShader ( "simple_vs.glsl" ).c_str ();
const char* fragmentShader = prm.LoadShader ( "simple_fs.glsl" ).c_str ();
GLuint vs = glCreateShader ( GL_VERTEX_SHADER );
glShaderSource ( vs, 1, &vertexShader, NULL );
glCompileShader ( vs );
GLuint fs = glCreateShader ( GL_FRAGMENT_SHADER );
glShaderSource ( fs, 1, &fragmentShader, NULL );
glCompileShader ( fs );
If I tried to compile it, I would get no errors, but there would be a black screen. If I removed the fragment shader, it would display a triangle, as it was meant to, without any colors. If I switched the two declarations, as in:
const char* fragmentShader = prm.LoadShader ( "simple_fs.glsl" ).c_str ();
const char* vertexShader = prm.LoadShader ( "simple_vs.glsl" ).c_str ();
I would get an error, and my program would crash:
Error code #3: Shader info for shader 1: WARNING: 0:1: '#version' :
version number deprecated in OGL 3.0 forward compatible context driver
ERROR: 0:1: '#extension' : 'GL_ARB_separate_shader_objects' is not
supported
However, if I put it like this:
const char* vertexShader = prm.LoadShader ( "simple_vs.glsl" ).c_str ();
GLuint vs = glCreateShader ( GL_VERTEX_SHADER );
glShaderSource ( vs, 1, &vertexShader, NULL );
glCompileShader ( vs );
const char* fragmentShader = prm.LoadShader ( "simple_fs.glsl" ).c_str ();
GLuint fs = glCreateShader ( GL_FRAGMENT_SHADER );
glShaderSource ( fs, 1, &fragmentShader, NULL );
glCompileShader ( fs );
It works perfectly fine. I am completely clueless as to why this is the case, as I ran the original code with no issues in prior versions of my program. I already checked the prm.LoadShader function, it works fine, and returns the expected value. None of the changes I have made to the program deal with shaders, so I am confused about this bizzarely particular behaviour. Can someone with more experience explain why exactly this is happening?
Upvotes: 0
Views: 379
Reputation: 110658
Presumably prm.LoadShader
returns a std::string
by value. Calling c_str
gives you the internal character storage of a std::string
, which only lives as long as the std::string
does. By the end of each of the LoadShader
lines, the std::string
that was returned is destroyed because it was a temporary object, and the pointers you've stored are no longer pointing at valid character arrays.
You can easily get around it by storing a local copy of the returned strings.
std::string vertexShader = prm.LoadShader ( "simple_vs.glsl" );
const char* cVertexShader = vertexShader.c_str();
std::string fragmentShader = prm.LoadShader ( "simple_fs.glsl" );
const char* cFragmentShader = vertexShader.c_str();
GLuint vs = glCreateShader ( GL_VERTEX_SHADER );
glShaderSource ( vs, 1, &cVertexShader, NULL );
glCompileShader ( vs );
GLuint fs = glCreateShader ( GL_FRAGMENT_SHADER );
glShaderSource ( fs, 1, &cFragmentShader, NULL );
glCompileShader ( fs );
Upvotes: 4