Reputation: 15213
I'm a C/C++ beginner trying to build what seems like a pretty simple program: it loads a file into a c-string (const char*). However, although the program is incredibly simple, it's not working in a way I understand. Take a look:
#include <iostream>
#include <fstream>
std::string loadStringFromFile(const char* file)
{
std::ifstream shader_file(file, std::ifstream::in);
std::string str((std::istreambuf_iterator<char>(shader_file)), std::istreambuf_iterator<char>());
return str;
}
const char* loadCStringFromFile(const char* file)
{
std::ifstream shader_file(file, std::ifstream::in);
std::string str((std::istreambuf_iterator<char>(shader_file)), std::istreambuf_iterator<char>());
return str.c_str();
}
int main()
{
std::string hello = loadStringFromFile("hello.txt");
std::cout << "hello: " << hello.c_str() << std::endl;
const char* hello2 = loadCStringFromFile("hello.txt");
std::cout << "hello2: " << hello2 << std::endl;
hello2 = hello.c_str();
std::cout << "hello2 = hello.c_str(), hello2: " << hello2 << std::endl;
return 0;
}
The output looks like this:
hello: Heeeeyyyyyy
hello2: 青!
hello2 = hello, hello2: Heeeeyyyyyy
The initial hello2 value changes every time, always some random kanji (I'm using a Japanese computer, so I'm guessing that's why it's kanji).
In my naive view, it seems like the two values should print identically. One function returns a c++ string, which I then convert to a c-string, and the other loads the string, converts the c-string from that and returns it. I made sure that the string was loading properly in loadCStringFromFile by couting the value before I returned it, and indeed it was what I had thought, e.g.:
/*(inside loadCStringFromFile)*/
const char* result = str.c_str();
std::cout << result << std::endl;//prints out "Heeeyyyyyy" as expected
return result;
So why should the value change? Thanks for the help...
Upvotes: 4
Views: 1795
Reputation: 12200
Your problem is that str
in loadCStringFromFile
is a local variable, and is destructed when the function returns. At that point the return value from c_str()
is invalid.
More detail here
Your first function, loadStringFromFile
, is a more C++-like way of doing it, and illustrates the benefit of having a class manage memory for you. If you use char* then you have to take much more care where memory is allocated and freed.
Upvotes: 4
Reputation: 36092
the function
std::string loadStringFromFile(const char* file)
returns a string copy of the string created inside the function which is copied before the string goes out of scope i.e. the function ends, that is why it works.
const char* loadCStringFromFile(const char* file)
on the other hand returns a pointer to the local string which goes out of scope when the function returns and is destroyed so the returned address, the const char*
, points to somewhere undefined.
in order for the second way to work you either need to create the string before calling the function :
const char* loadCStringFromFile(const char* file, string& str); // return str.c_str()
..
string str;
const char* result = loadCStringFromFile(file,str);
or you create a string on the heap in the function and pass the address back, but that gets a bit messy since the caller would need to delete the string to avoid memleak.
Upvotes: 3
Reputation: 2854
You should duplicate output of str.c_str():
return strdup(str.c_str);
function strdup
can be found in cstring header.
Upvotes: -1