Reputation: 817
I trying to use memcpy to copy content from one array to another, the code is as follow:
#include <stdio.h>
int main(){
int *a;
a = (int*) malloc(sizeof(int) * 4);
a[0] = 4;
a[1] = 3;
a[2] = 2;
a[3] = 1;
int *b;
b = (int*) malloc(sizeof(int) * 4);
memcpy(&b, &a, sizeof(a));
free(a);
for (int i = 0; i < 4; i++){
printf("b[%d]:%d",i,b[i]);
}
printf("%d\n",sizeof(b));
free(b);
return 0;
}
However, when I try to run it, I encounter the following error:
b[0]:4b[1]:3b[2]:2b[3]:18
mem(6131,0x7fffbb4723c0) malloc: *** error for object 0x7fa5a4c02890: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Abort trap: 6
This error disappear if I remove the free(b)
piece of code, however, I don't know why since I explicitly allocate resource to it.
Upvotes: 2
Views: 2689
Reputation: 134286
This is the exact problem why we say not to cast the return value of malloc()
and family in C
..
First things first, you are missing stdlib.h
include and because of that, the prototype of malloc()
is not known and your compiler assumnes that it returns an int
. This creates the mismatch between the implicit declaration and the actual definition, which at a later stage, invokes undefined behavior.
That said, another major issue is when you write memcpy(&b, &a, sizeof(a));
which is very wrong. You want to supply a
and b
themselves, as you want to copy the contents of the memory location pointed by a
to the memory location pointed by b
, not the address of the pointers.
In your case, the erroneous call actually messes up the contents of b
, i.e., the actual pointer returned by malloc()
. Therefore, as we know, passing a pointer which was not exactly returned by memory allocator functions or already free()
-d, to free()
causes UB, quoting C11
, chapter §7.22.3.3,
[...] Otherwise, if the argument does not match a pointer earlier returned by a memory management function, or if the space has been deallocated by a call to
free
orrealloc
, the behavior is undefined.
you're getting into trouble, as the current pointer held by b
is the same one as a
which has been already passed to free()
. As mentioned in the other answer(s) [1][2], you need to write
memcpy(b, a, sizeof(int)*4);
Moral of the story: Enable compiler warnings and always check the data types.
Upvotes: 3
Reputation: 7324
Your memcpy
is wrong. You're copying the value of the pointer a
into b
instead of copying the data pointed by a
into the buffer pointed by b
. You end up doing a double free because a
and b
point to the same place. Replace your memcpy
call with this:
memcpy(b, a, sizeof(int)*4);
Upvotes: 8
Reputation: 170045
memcpy(&b, &a, sizeof(a));
This doesn't copy the 4 ints that a
points at to the 4 ints that b
points at.
This instead overwrites b
with the contents of a
. Then you end up doing a double free, since both a
and b
contain the same address.
I'll repeat my comment on your question: You need to take the time to appreciate the difference between a pointer and a pointee. What holds and address, and what is at that address.
Upvotes: 5
Reputation: 864
Maybe because you free b when you do free(a). Because the memory zone is the same after doing memcpy. Try to do free(b) at the end, without the free(a).
Upvotes: 0