2

我正在尝试将 GLSL 顶点/片段着色器源加载到 const char* 数组中以与 OpenGL 一起使用。我用来做的功能是

const char* loadSource(const char* path)
{
   string line;
   stringstream output;
   ifstream source(path);

   if(source.is_open())
   {
       while(source.good())
       { 
           getline(source, line);
           output << line << endl;
       }
       source.close();
   }

   return output.str().c_str();
}

源输入在第一次调用时工作正常。但是,如果我调用第二个源,第一个源会“损坏”(两个调用都在单个函数的范围内):

const char* vs_source = loadSource("vertex.vert");  // vs_source loads fine
const char* fs_source = loadSource("fragment.frag"); // fs_source loads fine. vs_source is terminated sooner than after previous call.

注意:我尝试将 vs_source 直接编码到 *.cpp 文件中,并编译了两个着色器。这表明我必须在 loadSource 函数中做一些愚蠢的事情。

问题:是什么导致文本输入出现这种奇怪的行为?

4

3 回答 3

3

当您从函数返回结果时,您会创建一个悬空引用:

return output.str().c_str();

在表达式的末尾,std::string从流中获得的临时值被销毁,返回的内存变得无效:对数组的任何访问都会导致未定义的 bahvior。

顺便说一句,这种输入方法是错误的:

while(source.good())
{ 
    getline(source, line);
    output << line << endl;
}

读完总是需要检查读是否成功:

while (std::getline(source, line)) {
    output << line << '\n';
}

另外,不要使用std::endl. 如果您真的要刷新流,请使用std::flush. 最后,您可以更轻松甚至更快地获得相同的效果:

out << source.rdbuf();

...当然,out应该声明为std::ostringstream(而不是额外的o)。

于 2013-08-25T01:37:33.660 回答
1

是什么导致了文本输入的这种奇怪行为?

return output.str().c_str();

返回一个指向局部变量的指针,当函数loadSource返回output超出范围vs_source/fs_source时是悬空指针。访问vs_source/fs_source具有未定义的行为。

要解决您的问题,您可以改为返回 std::string :

std::string loadSource(const char* path)
{
    //...
    return output.str();
}

std::string vs_source = loadSource("vertex.vert");  // vs_source loads fine
std::string fs_source = loadSource("fragment.frag"); 
于 2013-08-25T01:37:29.703 回答
1

为什么大家都坚持做这种逐行读取文件呢?只需一次加载整个文件。这真的很简单:

std::string LoadFile(const std::string &filename)
{
    std::ifstream file (filename.c_str());
    if (file) {
        std::ostringstream os;
        os << file.rdbuf();
        return os.str();
    }
    else {
        // error
    }
}
于 2013-08-25T02:00:02.333 回答