0

I have a function,

std::string ReadShader(const std::string& filePath) {

    std::ifstream stream(filePath);
    std::string line;
    std::stringstream ss;

    while (getline(stream, line)) {

        ss << line << '\n';
    }

    return ss.str();
}

which works when I use these two lines of code,

std::string vertexShaderString = ReadShader("Shader/Vertex_Shader.vs");
const GLchar * vertexShaderSource = vertexShaderString.c_str();

i.e., vertexShaderString contains the expected string, and vertexShaderSource shows the first character of the expected string.

However, when I try a single line of code, viz.,

const GLchar * vertexShaderSource = (ReadShader("Shader/Vertex_Shader.vs")).c_str();

vertexShaderString has a consistent line of characters with a hex code of 0xdd, and vertexShaderSource shows the same 0xdd first character. That is, there is nothing of the expected string in either.

GLchar is an OpenGL typedef for char.

I think there is a C++ basic something I am missing.

1
  • 5
    The temporary lives until the ; ... so referencing its buffer after that is going to be problematic. Commented Jun 19, 2019 at 14:40

1 Answer 1

4

Your second version of the code is similar to this:

const GLchar * vertexShaderSource;
{
  std::string tmp = ReadShader("Shader/Vertex_Shader.vs");
  vertexShaderSource = tmp.c_str();
} // tmp is destroyed here

I hope this makes it more obvious that your pointer is referring to the contents of a std::string that has gone out of scope and deallocated its memory.

Sign up to request clarification or add additional context in comments.

5 Comments

Do I understand you to be saying that the returned value, ss.str(), goes out of scope by virtue of the outer enclosing parentheses, i.e., (ReadShader("Shader/Vertex_Shader.vs")), such that the subsequent call to c_str() is converting nonsense memory? If that is the case, than I cannot do what I wanted without passing in a reference or pointer to the ReadShader() function. I think that would work. Do you agree? Thanks for your answer.
No, the parentheses have absolutely nothing to do with it, they're completely redundant and make no difference to anything. The return value goes out of scope because it's a temporary variable and you don't copy it anywhere. Simply calling a member function to get a pointer from the temporary variable doesn't extend its lifetime and make it stay alive. It goes away at the end of the statement, and the pointer is left dangling, referring to deallocated memory. This is "a C++ basic something" that you're missing :-)
What's wrong with the first version of your code, copying the returned value into a local std::string variable, then calling c_str() on that? Why do you need to do it in one line?
There is nothing wrong with doing it in two lines. I was just being ornery and wanted to do it in one line! By so attempting, I learned something. Thanks for taking the time.
@user34299 It is safe to use the one-line approach only if you are passing the pointer to the temp object's data as a function parameter, eg: someFunc(ReadShader("Shader/Vertex_Shader.vs").c_str()); but it is not safe if you are saving the pointer after the temp is destroyed.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.