Reputation: 47
Can someone please explain why the following code segfaults whenever I attempt to do anything with either of the character arrays inside of the struct after I read it in from the binary file? The code is as follows:
struct my_struct {
int filename_len;
char *filename;
int size;
char *contents;
};
int main() {
FILE *fp = fopen("test.bin", "wb");
char *one = "list1";
char *two = "test file";
int one_len = strlen(one);
int two_len = strlen(two);
fwrite(&one_len, sizeof(int), 1, fp);
fwrite(&one, one_len, 1, fp);
fwrite(&two_len, sizeof(int), 1, fp);
fwrite(&two, two_len, 1, fp);
fclose(fp);
struct x *temp = malloc(sizeof(struct x));
fp = fopen("test.bin", "rb");
fread(&(temp->filename_len), sizeof(int), 1, fp);
fread(&(temp->filename), sizeof(char), temp->filename_len, fp);
fread(&(temp->size), sizeof(int), 1, fp);
fread(&(temp->contents), sizeof(char), temp->size, fp);
// This does not segfault
printf("%d\n", temp->filename_len);
// This does
printf("%s\n", temp->filename);
fclose(fp);
return 0;
}
Thank you!
Upvotes: 0
Views: 56
Reputation: 2866
1) You are calling fread
with the address of temp->filename
.
fread(&(temp->filename), sizeof(char), temp->filename_len, fp)
You don't want to do this. temp->filename
is already a pointer to a char. Instead pass simply temp->filename
.
2) You aren't allocating any space for temp->filename
. You need to do this after you read temp->filename_len
.
fread(&(temp->filename_len), sizeof(int), 1, fp);
temp->filename = malloc((temp->filename_len + 1) * sizeof(char))
fread(temp->filename, sizeof(char), temp->filename_len, fp);
temp->filename[temp->filename_len] = '\0';
Similarly for temp->contents
Upvotes: 1
Reputation:
fwrite(&one, one_len, 1, fp);
&one
is the address of the pointer one
on the stack, not the location it points to. This means that, instead of writing the string pointed to by one
, you're writing the bytes that make up its address, potentially along with whatever happens to come after that in memory.
fread(&(temp->filename), sizeof(char), temp->filename_len, fp);
Similarly, this reads a pointer (or part of a pointer) into temp->filename
, and may additionally overwrite whatever happens to be after it.
What you need to do is:
fwrite(one, one_len, 1, fp);
Write the actual contents of the string, not its address.
temp->filename = calloc(temp->filename_len + 1, sizeof(char));
fread(temp->filename, sizeof(char), temp->filename_len, fp);
Allocate a buffer sized appropriately for the filename, then read data into that buffer.
Upvotes: 2