c++fstreamlifetimeifstream

String seems to be deallocated after return from function


I am currently trying to make a simple function that reads a file's contents and stores it into either a std::string or char array. I have run into issues where the data is read completely fine within the function but it seems to be deleted / deallocated when the function is called.

I've isolated this problem to a small program:

Entry.cpp

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

const char* ReadFile(const std::string& path) {

    std::ifstream file;

    try {
        file.exceptions(std::ifstream::failbit | std::ifstream::badbit);
        file.open(path);

        if (!file.is_open()) {
            throw;
        }
    }
    catch (std::exception e) { //file does not exist
        std::string errmsg = "Unable to open file at path: " + path;

        std::cout << errmsg << std::endl;

        throw new std::exception(errmsg.c_str());
    }


    std::string contents;
    try {
        contents = std::string{ std::istreambuf_iterator<char>{file}, {} };
    }
    catch (const std::ifstream::failure& e) {

        std::cout << path << std::endl;
        std::cout << e.what() << std::endl;

        throw e;
    }

    std::cout << "----------------" << std::endl;
    std::cout << "in the function:" << std::endl;
    std::cout << contents.c_str() << std::endl;

    return contents.c_str();
}

int main() {
    const char* a = ReadFile("test.txt");

    std::cout << "----------------" << std::endl;
    std::cout << "in main" << std::endl;
    std::cout << a << std::endl;

    return 0;
}

test.txt

example content

dfhfrdhdf
h

srjed
jt
tejk
e
tktre
krtk

console logs

----------------
in the function:
example content

dfhfrdhdf
h

srjed
jt
tejk
e
tktre
krtk
----------------
in main
▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌

I have tried using strcpy to copy the data inside of the function which gave me various memory errors (although I may have used it wrong).


Solution

  • You are returning a pointer to the contents of a string, but unfortunately the string is destroyed when you exit the function, so your pointer is pointing at garbage.

    But the answer is very simple, just change the function to return a std::string.

    std::string ReadFile(const std::string& path) {
        ...
        return contents;
    }
    
    int main() {
        std::string a = ReadFile("test.txt");
        ...
        std::cout << a << std::endl;
    }
    

    If you really need a char* pointer to your string for some reason, then call .c_str() at the point you actually need it, not before.