我正在尝试将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函数中做一些愚蠢的事情。
问题:导致文本输入出现这种奇怪行为的原因是什么?
答案 0 :(得分:3)
当您从函数返回结果时,您将创建一个悬空参考:
return output.str().c_str();
在表达式结束时,从流中获取的临时std::string
将被销毁,并且返回的内存将变为无效:对数组的任何访问都会导致未定义的bhavior。
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
)。
答案 1 :(得分: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");
答案 2 :(得分:1)
为什么每个人都坚持要逐行阅读文件?只需load the whole file at once。这很简单:
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
}
}