I'm trying to implement simple fread()
and frwite()
example using strings. The program gives me segfault
or free(): invalid pointer
errors. Below is the example code I'm working with.
#include <fstream>
#include <iostream>
static bool file_read(FILE* file) {
std::string value="abcd";
std::string retrieved;
size_t read, write;
write = fwrite(&value, sizeof(value), 1, file);
fseek(file, 0, SEEK_SET);
read = fread(&retrieved, sizeof(value), 1, file);
return true;
}
int main(int argc, char *argv[]) {
FILE *file = NULL;
file = fopen("file_test", "wb ");
file_read(file);
fclose(file);
}
I checked if file
is opened correctly and that retrieved
has the same value as value
. I don't think I'm freeing any variables in my code. I'm suspecting that fread
is causing all the trouble.
fread(&retrieved[0], sizeof(char), 4, file)
Doesn't read the value to retrieved
and was where I am doing wrong.
CodePudding user response:
if you want to access the actual character buffer inside std::string you need to use value.c_str()
the length of the string is not given by sizeof, use value.length()
you cannot read from a file directly into a std::string
using fread
. You must read it into an intermediate char []
buffer and load from there. Or use ifstream
CodePudding user response:
std::string
is not a trivial type. It contains several private data members, including a pointer to character data that may reside in memory that is outside of the string object. So you can't read/write the raw bytes of the string object itself, like you are trying to do. You need to instead serialize its character data separately, eg:
#include <fstream>
#include <iostream>
#include <string>
#include <cstdio>
static bool file_writeStr(std::FILE* file, const std::string &value) {
size_t len = value.size();
bool res = (std::fwrite(reinterpret_cast<char*>(&len), sizeof(len), 1, file) == 1);
if (res) res = (std::fwrite(value.c_str(), len, 1, file) == 1);
return res;
}
static bool file_readStr(std::FILE* file, std::string &value) {
size_t len;
value.clear();
bool res = (std::fread(reinterpret_cast<char*>(&len), sizeof(len), 1, file) == 1);
if (res && len > 0) {
value.resize(len);
res = (std::fread(&value[0], len, 1, file) == 1);
}
return res;
}
static bool file_test(std::FILE* file) {
std::string value = "abcd";
std::string retrieved;
bool res = file_writeStr(file, value);
if (res) {
std::fseek(file, 0, SEEK_SET);
res = file_readStr(file, retrieved);
}
return res;
}
int main() {
std::FILE *file = std::fopen("file_test", "wb ");
if (file_test(file))
std::cout << "success";
else
std::cerr << "failed";
std::fclose(file);
}