1

假设我有这样的功能:

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. 我该如何解决?

4

2 回答 2

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

绑定到从返回vertex_shader_source的临时值“内部”的值。这根本不会“延长”临时的生命周期。一旦该语句的执行完成并继续,该临时内存(以及您现在持有的指针)将不再以定义的方式访问。std::stringget_shader

本质上,您正在调用未定义的行为。

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

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

如果你仍然const GLchar*在这一点上,vertex_shader_source.c_str()会做的。

于 2016-02-16T06:17:53.010 回答
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();
于 2016-02-16T06:16:43.477 回答