Why do these two pointers point to the same location after fread

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.
pointer magic.
you wrote the pointer to the file.
you loaded the pointer from the file.
your second struct now has the same pointer as the first struct, pointing to the same data.
its a convoluted way to get to this:
ss2.str = ss1.str; //this is what all the file save and load accomplishes

I am a little mystified that it shoveled the const char* into the struct's pointer field -- I guess it used C rules there, so no complaining about it?

you did not free the pointer, nor can you: they are not dynamic.
Last edited on
Thank you very much for the answer.
Sorry, I forgot to mention that this was meant to be a C program :|
Maybe that explains the C rules?

I feel like an idiot.. It never occured to me that it could be filling in the second pointer with the value read from the file.
Though, I guess that makes sense. And since I'm still in the same process, that memory location is valid and it all works out..

I guess I just assumed if it was getting the value from the file, it would have been treating it as the string "0x0011AABB"
and not the memory address 0x0011AABB. But why should it do that. The type is char*, so it treats it as char* 🤦‍♂️.

Thanks again, apparently I needed that to be pointed out to me.
Last edited on
if it helps, and a little oversimplified but generally speaking:

a pointer is a pointer. They are all just integers; its type (char*, double*, mystruct*, whatever) just ties in the size of the thing pointed to which is used to allocate and destroy it (or in c++, strong typing rules).

char* has a few special rules that no other type has. Basically you can work with it directly in odd ways that shortcut a lot of the pointer syntax. I advise you to actually use char arrays for strings in C; there are a number of reasons that take a while to appreciate.
Thank you for the help.
I'll try to keep the char[] vs char* in mind as well.
Topic archived. No new replies allowed.