Memcpy structure having pointers as members in C

Please do not vote if this is a stupid problem, I'm just trying to figure it out.

I have a structure with some pointers as elements, and I'm trying to execute memcpy, and they suggested that I don't use memcpy in this case, because memcpy makes a shallow copy (i.e. copies pointers) of a rather deep copy (which means copying to what the pointers indicate).

But I'm not sure why this does not make any difference in the following program: Please take a look at the code and the result and explain why in this case it is not a shallow copy?

#include <stdio.h> #include <malloc.h> #include <string.h> struct student { char *username; char *id; int roll; }; void print_struct(struct student *); void print_struct_addr(struct student *); void changeme(struct student *); int main (void) { struct student *student1; char *name = "ram"; char *id = "200ABCD"; int roll = 34; student1 = (struct student *)malloc(sizeof(struct student)); student1->username = name; student1->id = id; student1->roll = roll; print_struct_addr(student1); print_struct(student1); changeme(student1); print_struct(student1); print_struct_addr(student1); return 0; } void print_struct(struct student *s) { printf("Name: %s\n", s->username); printf("Id: %s\n", s->id); printf("R.No: %d\n", s->roll); return; } void print_struct_addr(struct student *s) { printf("Addr(Name): %x\n", &s->username); printf("Addr(Id): %x\n", &s->id); printf("Addr(R.No): %x\n", &s->roll); return; } void changeme(struct student *s) { struct student *student2; student2->username = "someone"; student2->id = "200EFGH"; student2->roll = 35; print_struct_addr(student2); memcpy(s, student2, sizeof(struct student)); student2->username = "somebodyelse"; return; } 

output:

 Addr(Name): 9b72008 Addr(Id): 9b7200c Addr(R.No): 9b72010 Name: ram Id: 200ABCD R.No: 34 Addr(Name): fa163c Addr(Id): fa1640 Addr(R.No): fa1644 Name: someone Id: 200EFGH R.No: 35 Addr(Name): 9b72008 Addr(Id): 9b7200c Addr(R.No): 9b72010 

If memcpy makes a shallow copy, then why student1-> username is NOT "someone".

Please explain in which scenario this code may cause a problem, I want the information student2 in student1 after calling changeme () in main () and subsequently can use this changed data student1.

I was asked NOT to use memcpy () here, but it seems to work fine.

thanks

This is a modified code: But I do not see the concept of a shallow copy here:

 #include <stdio.h> #include <malloc.h> #include <string.h> struct student { char *username; char *id; int roll; }; void print_struct(struct student *); void print_struct_addr(struct student *); void changeme(struct student *); int main (void) { struct student *student1; char *name = "ram"; char *id = "200ABCD"; int roll = 34; student1 = malloc(sizeof(*student1)); student1->username = name; student1->id = id; student1->roll = roll; print_struct_addr(student1); print_struct(student1); changeme(student1); print_struct(student1); print_struct_addr(student1); return 0; } void print_struct(struct student *s) { printf("Name: %s\n", s->username); printf("Id: %s\n", s->id); printf("R.No: %d\n", s->roll); return; } void print_struct_addr(struct student *s) { printf("Addr(Name): %x\n", &s->username); printf("Addr(Id): %x\n", &s->id); printf("Addr(R.No): %x\n", &s->roll); return; } void changeme(struct student *s) { struct student *student2; student2 = malloc(sizeof(*s)); student2->username = strdup("someone"); student2->id = strdup("200EFGH"); student2->roll = 35; print_struct_addr(student2); memcpy(s, student2, sizeof(struct student)); student2->username = strdup("somebodyelse"); free(student2); return; } 
+4
source share
3 answers

It:

 struct student *student2; student2->username = "someone"; student2->id = "200EFGH"; student2->roll = 35; 

Writes to unallocated memory, causing undefined behavior. You must make sure that before writing student2 indicates that it is valid somewhere.

Either select it, or use an on-stack instance, since you are still going to copy it.

Of course, this whole operation of initializing student2 , and then rewriting s with it is uselessly complicated, you just have to change s directly.

In addition, these are:

 student1 = (struct student *)malloc(sizeof(struct student)); 

It’s better to write in C since:

 student1 = malloc(sizeof *student1); 

This removes the meaningless (and potentially dangerous) listing and ensures that the size is correct for this type, replacing the dependency checked by the programmer with one handled by the compiler.

Thirdly, this is a slightly classic β€œsymptom” of a novice C programmer, so as not to understand that you can assign structures. So instead

 memcpy(s, student2, sizeof *s); 

You can simply write:

 *s = *student2; 

And let the compiler be correct. This could be a win in performance, because the structure may contain many additions that the destination may know and not copy, but which memcpy() cannot ignore.

+11
source

The fact that this generally works is an accident. In your changeme() function, you create a new pointer for student2 , but you do not allocate memory for it.

Secondly, in the same function, you change student2 after you copied it to s . A shallow copy does not mean that any pointers in the copies are shared β€” it means that the values ​​of the pointers themselves are also copied. Therefore, when you change student2->username after memcpy , it does not change the value s->username .

As you progress, you also need to be more careful with the allocation of memory within these structures. AFAICR, if you use a constant literal string, then the pointer will point to a fragment of statically initialized data in the program memory. However, a stricter construct would have malloc() and free() dynamic memory for these elements. If you ever needed a statically initialized value, you would use strdup() or similar to copy a string from static space to heap memory.

+2
source

After copying, you set the username "somebodyelse". And this only changes the local copy inside the "changeme ()" function. Try printing student2 inside "changeme ()" and you will see what I mean.

0
source

Source: https://habr.com/ru/post/1442966/


All Articles