0

Considering the following code (it uses OpenGL but that's not what my question is about):

#include <iostream>
#include <sstream>
#include <fstream>
#include <string>

using std::string;

...

//Example func for loading content of external file
string load(string src) {
    std::ifstream file(src);

    if (file.fail()) {
        output("FILE", "Failed to access content of file at location " + string(src), 1);
    }

    string content;

    while (!file.eof()) {
        char character;
        file.get(character);
        content.push_back(character);
    }
    content.pop_back();

    return content;
};

unsigned int compileShader() {
    // Create shader
    unsigned int shader;
    shader = glCreateShader(type);
    string codeString = load(src); // Load shader from file here
    const char* code = codeString.c_str(); // Convert to C string (needed in further computations)

    // What does the code look like?
    std::cout << code << std::endl;

    // --> Finish to compute shader based on gathered code, etc.
    glShaderSource(shader, 1, &code, NULL);


}

...

The compileShader() function, thus, loads the content of an external file written in GLSL, then converts the result to a C string as needed in order to be passed as an argument to the GL function glShaderSource(). And it works just fine.

Focusing only on this snippet, however:

string codeString = load(src); // Load shader from file here
const char* code = codeString.c_str(); // Convert to C string

// What does the code look like?
std::cout << code << std::endl;

This works properly. The std::cout statement prints the content of the shader at execution; the compilations succeeds. Yet I realized by accident (by trying to take shortcuts, that is) that the following doesn't work:

const char* code = load(src).c_str(); // Load shader from file and convert to C string 

// What does the code look like?
std::cout << code << std::endl;

The std::cout just prints a line instead of the file's content. Why is it so? I suppose it's a question of precedence (of the method over the function, perhaps?), but I've tried setting the function in brackets (as if it were a mathematical operation), to no avail.

What's preventing it from working? What are the underlying mechanics behind this? Thank you for your answers. I'm relatively new to C++, so it might really be simple, only I don't know where else exactly to search for an answer.

Thurinum
  • 128
  • 3
  • 13
  • 1
    Unrelated to your problem, but please read [Why is iostream::eof inside a loop condition (i.e. `while (!stream.eof())`) considered wrong?](https://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-i-e-while-stream-eof-cons) – Some programmer dude May 01 '20 at 21:28
  • 2
    Be wary the temporary variable, my friend. They do not live long and pointers to them are fraught with peril. – user4581301 May 01 '20 at 21:31
  • `if (file.fail())` -- You check for failure, but your code calls `output` and continues on into the function as if nothing is wrong. – PaulMcKenzie May 01 '20 at 21:31
  • As for your problem: `load(src).c_str()` will get the pointer to the contents of a *temporary* object, an object which will be destructed as soon as the assignment is finished. That will leave you with an invalid pointer, and attempting to dereferencing it will lead to [*undefined behavior*](https://en.wikipedia.org/wiki/Undefined_behavior) – Some programmer dude May 01 '20 at 21:32
  • @PaulMcKenzie Perhaps it does, but I believe it will end up returning an empty string. That's questionable, but not *entirely* wrong. – HTNW May 01 '20 at 21:37
  • @Someprogrammerdude Okay, so it's basically converting to Cstr a temporary variable that no longer exist in memory? Makes sense. – Thurinum May 01 '20 at 21:37
  • @PaulMcKenzie I left it like that because OpenGL will automatically create a log when trying to process the shader data, so even if the file's content was invalid it would produce an error (which can be gathered with a specific function). Didn't put it because I thought it irrelevant in the context. – Thurinum May 01 '20 at 21:37
  • @Optimum94 think of it as providing a pointer to a buffer that's owned by the returned `std::string`. Since the `string` wasn't assigned to anything, it promptly vanishes, taking it's buffer with it and leaving you with a pointer to invalid memory. – user4581301 May 02 '20 at 01:09

0 Answers0