为什么我的 std::字符串通过流获得被覆盖

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

本文关键字:覆盖 我的 std 字符串 为什么      更新时间:2023-10-16

假设我有一个这样的函数:

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电话所淹没.我该如何解决这个问题?

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

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

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

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

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

如果你在这一点上仍然是const GLchar*vertex_shader_source.c_str()就可以了。

对于语句,

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