【问题标题】:Why is my std::string obtained via stream being overwritten?为什么我通过流获得的 std::string 被覆盖?
【发布时间】:2016-02-16 06:12:26
【问题描述】:

假设我有这样的功能:

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 的调用所掩盖。我该如何解决这个问题?

【问题讨论】:

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


    【解决方案1】:
    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() 就可以了。

    【讨论】:

    • 只是想明白:我认为 get_shader() 会返回字符串的副本,那么指向 c_str() 的指针在范围的其余部分内是否有效?
    • 是的,它确实返回了一个副本。该副本是临时的。调用c_str() 函数后,您将获得一个指向临时std::string 的内部“c 字符串”的指针。一旦临时对象被销毁,该指针将不再有效,并且尝试访问它不会按照您希望的方式工作。
    • 啊,我在想对 get_shader() 的调用相当于在当前范围内创建一个std::string,但我现在看到它只存在到调用它的语句的末尾.谢谢。
    【解决方案2】:

    对于声明,

    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

    你看到的可能是deallocated后内存重用造成的,但是UB就是UB,一切皆有可能。

    你可以为它定义一个命名变量,例如:

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

    【讨论】:

      猜你喜欢
      • 2022-06-14
      • 2011-09-22
      • 2011-04-12
      • 2022-01-20
      • 1970-01-01
      • 1970-01-01
      • 2020-04-19
      • 2019-06-01
      • 1970-01-01
      相关资源
      最近更新 更多