-1

I've had to stop coding so many projects because of this weird quirk that I'm fed up enough to ask and risk looking like an idiot, so here goes...

I wrote a function like this:

const char* readFileToString(const char* filename) {
    const char* result;
    std::ifstream t(filename);
    std::stringstream buffer;
    buffer << t.rdbuf();
    result = buffer.str().c_str();
    return result;
}

I would expect that, if file.txt contains hello, that readFileToString("file.txt") should return hello. Instead, it returns garbled text, something along the lines of H�rv�0. However, if I put a std::cout << result; just before the return, it'll print hello.

Is this some weird, impossible quirk with C++? How do I fix it?

Ethan McTague
  • 2,236
  • 3
  • 21
  • 53
  • 3
    Returning pointers to local or temporary variables is rarely a good idea. Just use std::string, returned by value. –  Apr 23 '17 at 15:22

2 Answers2

2

It's neither weird nor impossible; you returned a pointer to a buffer that went out of scope. The const char* doesn't "own" the string data, it only refers to it. Or, it used to! Once returned, that pointer is now invalid. You shall not dereference it.

I suggest you stick with std::string instead of venturing into advanced pointer techniques.

std::string readFileToString(const char* filename)
{
    std::ifstream t(filename);
    std::stringstream buffer;
    buffer << t.rdbuf();
    return buffer.str();
}

Unfortunately, I am not aware of any way to avoid a copy here.

If you don't mind shuffling your design about a little, and if you have some way to avoid a stream-to-string copy down the line, you could do this instead:

void readFileToStream(const char* filename, std::ostream& os)
{
    std::ifstream t(filename);
    os << t.rdbuf();
}

You may wish to return bool signifying the stream's state, but again you can do that at the callsite anyway.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
1

Please see the commentary below:

const char* readFileToString(const char* filename) {
    const char* result;
    std::ifstream t(filename);
    std::stringstream buffer; // Behind the scenes some memory will/is allocated
    buffer << t.rdbuf();      // Memory is getting filled 
    result = buffer.str().c_str(); // Getting the address of that memory
    return result;
    // Buffer getting destroyed along with the allocated memory (what result points to)
}

.. Here results points to an invalid memory location

So hence it being corrupted

Ed Heal
  • 59,252
  • 17
  • 87
  • 127