在std :: string中滥用GL info log null终止字符?

时间:2016-02-04 14:04:06

标签: c++ c++11 opengl stdstring

我有一个相当简单的log()方法用于GL着色器和程序便利类,因为相应的compilelink方法只返回bool,同时隐藏所有GL呼叫;如,

std::string
glShader::log () const
{
    std::string info;
    GLint len = 0;

    if (!glIsShader(gl_shader_obj))
        info = "(invalid shader object)\n";
    else
        glGetShaderiv(gl_shader_obj, GL_INFO_LOG_LENGTH, & len);

    if (len != 0)
    {
        info.resize(static_cast<std::string::size_type>(len));
        glGetShaderInfoLog(gl_shader_obj, len, NULL, & info[0]);
    }

    return info;
}

这是对std::string::resize (size_type)参数的误用吗?我知道C ++ 11在查询时要求一个空终止字符,即c_str();但它是否保证其存在?这可能是实现string以简化C字符串访问的“合理”方式,但不是必需的。

但是,如果有日志,GL_INFO_LOG_LENGTH包含日志中字符数的\0;否则日志长度只是零。

我是否可能以这种方式写出string保留缓冲区的末尾?我应该在(len - 1)电话中使用InfoLog吗?或者我对C ++ 11字符串的想法有误吗?也就是说,我可以使用null终止符安全地覆盖吗?

1 个答案:

答案 0 :(得分:3)

是的,这是对std::string的有效使用。您可以获得指向第一个字符的指针并写入字符数组,只要您不超出范围[0,size())。

然而,你确实犯了一个错误。请参阅GL_INFO_LOG_LENGTH在长度中包含NUL终止符。这意味着,从技术上讲,您的std::string比其需要的字符长一个字符。 info的最后一个字符将是一个NUL字符,而std::string会将它视为字符串数据的一部分,而不是标记字符串结尾的分隔符。< / p>

您应该尝试通过在设置len的尺寸之前从info中减去1来解决此问题。为什么?因为glGetShaderInfoLog总是 NUL终止它写入的字符串。因此,如果缩小len,它将从日志中删除最后一个实际字符。

相反,您应该在从OpenGL复制后缩小info

info.resize(static_cast<std::string::size_type>(len));
glGetShaderInfoLog(gl_shader_obj, len, NULL, & info[0]);
info.pop_back();

在C ++ 17中,标准写法已经改为允许写入字符串的NUL终结符,只要你用NUL字符覆盖它。它还允许string::data返回非const字符数组。因此,现在可以正常工作:

info.resize(static_cast<std::string::size_type>(len - 1));
glGetShaderInfoLog(gl_shader_obj, len, NULL, info.data());

标准要求info的大小为+ 1个字节。