Hello,
I recently wrote something like this and was surprised by its behaviour.
My attempt at distilling the surprising bit to a minimal repro follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
#include<stdio.h>
struct StringStruct {
char *str;
};
int main() {
struct StringStruct ss1 = {"This is a long string. Like, it's definitely longer than 8 bytes."};
FILE *fp = fopen("structString.bin","wb");
fwrite(&ss1,sizeof(struct StringStruct),1,fp);
fclose(fp);
struct StringStruct ss2;
fp = fopen("structString.bin","rb");
fread(&ss2,sizeof(struct StringStruct),1,fp);
fclose(fp);
printf("Read from file: %s\n",ss2.str);
return 0;
}
|
I know the code is broken BTW. It's writing the pointer ( and not the string pointed to by the pointer) to the file.
Which is why I didn't expect it to work. But when I run this program, the output is:
|
read from file: This is a long string. Like, it's definitely longer than 8 bytes
|
Which surprised me.
I checked the file size, and sure enough, it's only 8b. So, no string there.
Yet, the output shows the string.
I fired up gdb and had a look at ss1 and ss2. At declaration, their `str` fields point to different locations.
But, after the fread() ss2.str points to the memory location ss1.str points to, and it contains the string.
My question is why is this happening?
I thought maybe since I'm not allocating memory for these, they were pointing at the start of the memory space of the process?
But it didn't look like it. And even if it did, that wouldn't explain the change in ss2.str after the fread().
(bonus question I guess: ) Should I even have allocated memory for them? Aren't these going to live temporarily on the stack anyway?
Thanks in advance.
P.S. If you don't feel like giving a lecture on C memory management in a forum post,
and instead would like to direct me to a book chapter or something, I will gladly accept that as well.