Why is my std::string obtained via stream being overwritten?

孤街浪徒 提交于 2019-12-11 13:17:19

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!