为什么我的std :: string通过流被覆盖?

时间:2016-02-16 06:12:26

标签: c++ ifstream stdstring c-strings ostringstream

假设我有这样的功能:

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();
}

然后是一些像这样的代码:

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

我不明白为什么vertex_shader_source会因后来调用get_shader而被覆盖。我该如何解决这个问题?

2 个答案:

答案 0 :(得分:3)

const GLchar * vertex_shader_source = get_shader("triangle_vertex.vs").c_str();

vertex_shader_source绑定到一个值&#34; inside&#34;从std::string返回的临时get_shader。这不会延长&#34;暂时的生命。一旦该语句的执行完成并继续,就不再能以定义的方式访问该临时内存(以及您现在拥有的指针)。

基本上你是在调用未定义的行为。

vertex_shader_source的更合适的声明可以是std::string。由于该值是从函数返回的,因此它是一个右值,并且将调用适当的移动构造。

std::string vertex_shader_source = get_shader("triangle_vertex.vs");

如果您此时仍然是const GLchar*vertex_shader_source.c_str()将会这样做。

答案 1 :(得分:1)

声明,

const GLchar * vertex_shader_source = get_shader("triangle_vertex.vs").c_str();
// The temporary `std::string` will be destroyed here.

get_shader返回一个临时std::string,它将在语句后被销毁,这意味着vertex_shader_source将保留一个无效指针,取消引用它将导致UB

你看到的内容可能是由解除分配后的内存重用引起的,但是UB是UB,一切皆有可能。

您可以为其定义命名变量,例如:

std::string vertex_shader_source_string = get_shader("triangle_vertex.vs");
const GLchar * vertex_shader_source = vertex_shader_source_string.c_str();