简体   繁体   中英

Free a pointer equal to a malloc pointer

I'm having trouble understanding some of the free() behavior.

int* ptr1 = (int*)malloc(sizeof (int)*10);
int* ptr2 = ptr1;
free(ptr2);

Is the free(ptr2) going to delete my array as I want ?

What if I do :

int** ptr1 = (int**)malloc(sizeof (int)*10);
int* ptr2 = (int*)malloc(sizeof (int));
*ptr2 = 10;
ptr1[0] = ptr2;
free(ptr1);

Is this code correct ? Will free(ptr1) will also delete the space of ptr2 ?

Thanks

Yes and no, respectively.

Also note that malloc(sizeof(int)*10); in the second example will work, but it will not necessarily allocate space for ten pointers.


To explain what happens in the first example, after the assignment to ptr2 you have something like this:

+------+
| ptr1 | ---\
+------+     \      +----------------------------+
              >---> | memory allocated by malloc |
+------+     /      +----------------------------+
| ptr2 | ---/
+------+

Both variables contain the same value, the pointer returned by malloc , so you can use either of them to access the allocated memory.

For the second question, what you have is something like this:

+---------+---------+---------+-----+
| ptr1[0] | ptr1[1] | ptr1[2] | ... |
+---------+---------+---------+-----+
  |
  |
  v
+----------------------------+
| memory allocated by malloc |
+----------------------------+
  ^
  |
  |
+------+
| ptr2 |
+------+

When you free the memory pointer to by ptr1 that only frees that memory, the memory pointed to by ptr2 is still there and accessible through ptr2 .

malloc and free do not know about your data structures. All they know about is blobs of bytes.

As a general rule, there should be a one-to-one relationship between your malloc and free calls. (There are plenty of exceptions, but it's a good general rule.)

It is never the case that a single call to free will simultaneously free two separate blocks allocated by two calls to malloc .

So, as others have said, the answers to your questions are "Yes" and "No".

int* ptr1 = (int*)malloc(sizeof(int)*10);
int* ptr2 = ptr1;
free(ptr2);

That is fine, ptr2 contains the same value as ptr1 , and thus the memory you passed to malloc() is free() d.

int** ptr1 = (int**)malloc(sizeof(int)*10);
int* ptr2 = (int*)malloc(sizeof(int));
*ptr2=10;
ptr1[0]=ptr2;
free(ptr1);

That is not fine. You are storing the value of ptr2 in the ptr1 array, but not freeing it. You want:

int** ptr1 = (int**)malloc(sizeof(int*)*10);
int* ptr2 = (int*)malloc(sizeof(int));
*ptr2=10;
ptr1[0]=ptr2; 
...
free(ptr1[0]);
free(ptr1);

Note I have also changed the malloc() to allocate 10 pointers to int , not merely ten int s (which may not be the same size).

Finally note that you don't need to cast the return value from malloc() in C. I haven't fixed that for you as it is not a problem in itself and is unrelated to your question, but it is (arguably) bad style.

Is the free(ptr2) going to delete my array as I want ?

I think the term delete cannot be used here. The GNU manual says :

When you no longer need a block that you got with malloc, use the function free to make the block available to be allocated again.

However free doesn't set pointer automatically to NULL because the function return type itself is void . Also,

Freeing a block alters the contents of the block. Do not expect to find any data (such as a pointer to the next block in a chain of blocks) in the block after freeing it.

I am not spurring a debate on whether you should set the pointer to NULL after freeing it. However,I felt tempted to post this example which crashes and burns :

#include<stdio.h>
#include<stdlib.h>
int main()
{
    int* ptr1 = malloc(sizeof(int)*10);
    int* ptr2 = ptr1;
    free(ptr2);
    if(ptr2!=NULL)
    {
        printf("ptr is %p\n",ptr2); // still printf
        printf("Enter a number for ptr2 :");
        scanf("%d",ptr2);
        printf("Value pointed to by ptr2 : %d\n",*ptr2);
        printf("Value pointed to by ptr1 : %d\n",*ptr1);
    }
    else
        printf("Ptr2 pointed to null");
    printf("Size of ptr1 : %d\n",sizeof(ptr1));

    if(ptr1==NULL)
        printf("ptr1 NULL\n");
    printf("Enter a number for ptr1 :");
    scanf("%d",ptr1);
    printf("Value pointed to by ptr1 : %d\n",*ptr1);
    printf("Value pointed to by ptr2 : %d\n",*ptr2);

    free(ptr1);
    if(ptr1==NULL)
        printf("ptr1 freed\n");

    return 0;
}

Output

ptr is 0x1c92010
Enter a number for ptr2 :4
Value pointed to by ptr2 : 4
Value pointed to by ptr1 : 4
Size of ptr1 : 8
Enter a number for ptr1 :1
Value pointed to by ptr1 : 1
Value pointed to by ptr2 : 1
*** glibc detected *** ./testp: double free or corruption (fasttop): 0x0000000001c92010 ***
Segmentation fault (core dumped)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM