从方法非确定性行为返回 std::字符串
Returning std::string from method non-deterministic behavior?
我有一个读取文件并将其内容作为std::string
返回的方法。我使用返回的std::string
来编译一个 OpenGL 程序。在某些情况下,链接失败(编译的顶点着色器已损坏),因为NULL
了一个或两个着色器部分(读取文件内容)。
- 如果我逐步调试我的代码,一切都很好。
- 如果我打印文件内容,链接似乎失败的频率较低。
为什么它的行为不同,我的错误在哪里?
末尾的cout
始终打印正确的文件内容:
std::string read_file(const char* filePath) {
std::string content;
std::ifstream stream(filePath, std::ios::in);
if (stream.is_open()) {
std::string line = "";
while(getline(stream, line)) {
content += "n" + line;
}
}
std::cout << "read_file " << content << "end read_file" << std::endl; // always prints the correct content
return content; // makes a copy, don't like that, unless RVO?..
}
fragmentSource
和/或vertextSource
有时为空:
GLuint fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
GLuint vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
const char* fragmentSource = tools::read_file(_fragmentShaderPath).c_str();
std::cout << "vertext shader source: " << std::endl << fragmentSource; // empty sometimes
glShaderSource(fragmentShaderID, 1, &fragmentSource, NULL);
glCompileShader(fragmentShaderID);
CheckCompilation(fragmentShaderID);
const char* vertexSource = tools::read_file(_vertexShaderPath).c_str();
std::cout << "vertext shader source: " << std::endl << vertexSource; // empty sometimes
glShaderSource(vertexShaderID, 1, &vertexSource, NULL);
glCompileShader(vertexShaderID);
CheckCompilation(vertexShaderID);
GLuint programId = glCreateProgram();
glAttachShader(programId, fragmentShaderID);
glAttachShader(programId, vertexShaderID);
glLinkProgram(programId);
GLint result = GL_FALSE;
GLint infoLogLength;
glGetProgramiv(programId, GL_LINK_STATUS, &result);
glGetProgramiv(programId, GL_INFO_LOG_LENGTH, &infoLogLength);
if (infoLogLength > 0) { // this fails sometimes, corresponding to either vertexSource or fragmentSource being empty
std::vector<char> infoLog(infoLogLength + 1);
glGetProgramInfoLog(programId, infoLogLength, NULL, &infoLog[0]);
std::cout << &infoLog[0] << std::endl;
}
替换
const char* fragmentSource = tools::read_file(_fragmentShaderPath).c_str();
跟
std::string fragmentSourceStr = tools::read_file(_fragmentShaderPath);
const char* fragmentSource = fragmentSourceStr.c_str();
vertexSource
也是如此.
问题是您返回的字符串是临时字符串,因此在使用指向其数据的指针初始化fragmentSource
后,它会被销毁,这使fragmentSource
指向已销毁的存储。
如果是我,我宁愿只处理 c++ 类型,直到我们真正接触 openGL C api。
因此,首先我将在 tools
命名空间中创建一个轻量级代理函数:
namespace tools {
auto shaderSource(GLuint shaderId, const std::string& source)
{
auto ptr = std::addressof(source[0]);
return glShaderSource(shaderId, 1, std::addressof(ptr), nullptr);
}
}
然后完全替换原始指针的使用:
auto fragmentSource = tools::read_file(_fragmentShaderPath);
std::cout << "vertext shader source: " << std::endl << fragmentSource; // empty sometimes
tools::shaderSource(fragmentShaderID, fragmentSource);
相关文章:
- 我可以重新分配/覆盖std::字符串吗
- 如何将这个std::字符串转换为std::基本字符串
- std::字符串与 PCWSTR 的对话
- 重载 std::字符串运算符+ 用于打印枚举名称
- 从std::字符串创建OssBitString
- std::字符串擦除以删除最后一个字母
- 如何使用 C++ 中的原语初始化类(如 std::字符串从 const char* 初始化)
- std::字符串串联操作
- 如何有效地将一个大std::字符串的一部分转换为float
- 转义std::字符串中的特殊字符
- 用C++替换std::字符串中的一个子字符串,但不能全部替换
- C++std::字符串流到常量字符*的转换
- 如何将std::字符串转换为不同的字符串类
- 对齐C++字符串类型问题 std::字符串到 TStr
- std::字符串到字符*而不切割字节
- 编写具有非ASCII数据的std ::字符串
- 将 Delphi 的字符串转换为 std::字符串用于C++
- std::字符串添加到字符*
- 字符* 和 std::字符串和常量字符*之间的转换
- 用指针访问std ::字符串中的元素