问题
gcc (GCC) 4.7.0
c89
Hello,
I have the following structure that I am trying to fwrite and fread.
However, because my device and resource are pointers. The fwrite will read the pointer values and not the data. I cannot use a array for the device or resource. Only pointers as they have to be dynamically allocated.
I allocate all memory for the structure elements before I write. Not shown here as I want to keep the snippet short. Nor is free'ing.
In my fread function, I allocate the memory for the device and resource so that the fread will read into these memory locations. However, this will not work.
What is the best way to do this?
Many thanks for any advice,
struct data {
int id;
int set;
char *device;
char *resource;
};
struct database {
struct data **db_data;
size_t database_rows;
size_t database_data_size;
};
int database_write(FILE *fp, const struct database *db)
{
rewind(fp);
if(fwrite(*db->db_data, sizeof(struct data), 1, fp) == -1) {
return DATABASE_ERROR;
}
return 0;
}
struct database* database_read(FILE *fp, size_t db_rows, size_t db_data_size)
{
struct database *db = NULL;
size_t i = 0;
db = malloc(sizeof(struct database));
db->database_rows = db_rows;
db->database_data_size = db_data_size;
db->db_data = malloc(sizeof(struct data) * db_rows);
for(i = 0; i < db_rows; i++) {
db->db_data[i] = malloc(sizeof(struct data));
db->db_data[i]->device = malloc(db_data_size);
db->db_data[i]->resource = malloc(db_data_size);
}
rewind(fp);
if(fread(*db->db_data, sizeof(struct data), 1, fp) == -1) {
return NULL;
}
return db;
}
回答1:
You seem to have answered your own question, fread and fwrite just look at what's in memory and put that in the file. This works great if you're writing things that don't have pointers (e.g. big arrays of numbers). It's not designed to write structs with pointers.
If this file has a format, you need to do what the format says. If you're making up a format as you go, then you should write each member one by one into the file. You will need some sort of buffer to read into (you may need to resize this if you don't have a maximum length specification). Also, your database_write function will need to be changed quite a bit as well.
回答2:
If device
and resource
can have variable length you should write down the size of device
and then the data. Do the same for resource
.
When you read them back you can read the size, then allocate memory and finally read the value.
回答3:
You have yourself described you problem. fwrite will write the address and not the value.
May be you can use a field for the length of device and resource in your structure "struct data". Create a wrapper for fread() and fwrite() which reads/writes this length. In this wrapper you can memcpy devices, resource in a temporary buffer and use fwrite() on it.
This is a simple and very basic solution.
While sending packets in networks, you will generally see a structures containing char pointers. The first 4/8 bytes store the length of the data and the remaining bytes contain the actual data. User reading the packet, first reads the beginning 4/8 bytes. Depending on this, read() call is issued to read the remaining data.
You may refer Is the "struct hack" technically undefined behavior?
来源:https://stackoverflow.com/questions/12581165/freading-and-fwriteing-a-structure-that-contains-pointers