Long Thai
Long Thai

Reputation: 817

"pointer being freed was not allocated" while using memcpy

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

Answers (4)

Sourav Ghosh
Sourav Ghosh

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 or realloc, 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

Kevin
Kevin

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

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

Sergio
Sergio

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

Related Questions