问题
Assume I have a function like so:
std::string get_shader(std::string path) {
std::string fullpath = "./resources/shaders/" + path;
std::ifstream vertexShaderFile(fullpath);
std::ostringstream vertexBuffer;
vertexBuffer << vertexShaderFile.rdbuf();
return vertexBuffer.str();
}
And then some code like this:
GLuint vertex_shader;
GLuint fragment_shader;
GLuint program;
const GLchar * vertex_shader_source = get_shader("triangle_vertex.vs").c_str();
// At this point vertex_shader_source is correct.
const GLchar * fragment_shader_source = get_shader("fragment.vs").c_str();
// Now vertex_shader_source is the same as fragment_shader_source
I don't understand why vertex_shader_source
ends up being overwitten by a subsequent call to get_shader
. How do I fix this?
回答1:
const GLchar * vertex_shader_source = get_shader("triangle_vertex.vs").c_str();
The vertex_shader_source
is bound to a value "inside" the temporary std::string
returned from get_shader
. This does not "extend" the lifetime of the temporary at all. Once the execution of that statement is complete and continues, that temporary, and it's memory (and the pointer you now hold) is no longer accessible in a defined manner.
Essentially you are invoking undefined behaviour.
A more appropriate declaration of the vertex_shader_source
could be as a std::string
. Since the value is being returned from the function, it is a rvalue and the appropriate move construction will be invoked.
std::string vertex_shader_source = get_shader("triangle_vertex.vs");
If you still the the const GLchar*
at this point, vertex_shader_source.c_str()
will do.
回答2:
For the statement,
const GLchar * vertex_shader_source = get_shader("triangle_vertex.vs").c_str();
// The temporary `std::string` will be destroyed here.
get_shader
returns a temporary std::string
, which will be destroyed after the statement, that means vertex_shader_source
will hold an invalid pointer, dereference of it will lead to UB.
What you have seen might be caused by the memory reuse after deallocated, but UB is UB, anything is possible.
You could define a named variable for it, such as:
std::string vertex_shader_source_string = get_shader("triangle_vertex.vs");
const GLchar * vertex_shader_source = vertex_shader_source_string.c_str();
来源:https://stackoverflow.com/questions/35425068/why-is-my-stdstring-obtained-via-stream-being-overwritten