简体   繁体   中英

Two pointers are pointing to same memory address, how to avoid memory leak in case freeing of these two happens at independence place?

int *a = malloc(40);
int *b;
b=a;
if( *some conditions* )
free(a);
// I know that 'a' has been allocated this chunk of memory X times
// and free(a) has been called less than X times.

I have no idea of that condition, so don't know whether 'a' has been freed or not! So now how would I be sure if 'b' ie 'a' has been freed or not.

If you want to make sure that subsequent calls of free on a pointer to dynamically allocated memory will not do any harm, you should assign NULL to that pointer. Because (emphasis added):

The free() function frees the memory space pointed to by ptr, which must have been returned by a previous call to malloc(), calloc() or realloc(). Otherwise, or if free(ptr) has already been called before, undefined behavior occurs. If ptr is NULL, no operation is performed.

If you want to make sure that pointer b will always refer to the same object the other pointer a points at, you could turn b into a pointer to a instead (and dereference it each time you need to use it):

#include <stdio.h>
#include <stdlib.h>

int main() {
    /* dynamically allocate some memory */
    int *a = malloc(40);
    /* b is a pointer to a pointer to an int */
    int **b;
    /* make b point to a */
    b = &a;
    if ( 1 ) {
        /* free memory and assign NULL to the pointer */
        free(a);
        a = NULL;
    }
    /* nothing bad will happen when we dereference b now */
    printf("%p\n", *b);
    /* nothing bad will happen when we free the memory region
       where the pointer b points to points to */
    free(*b);
}

Another thing on memory leaks. There will be no memory leaked when you double-free the memory. In that case you will stumble into undefined behavior, in which case anything could happen . Simply because you shall not access memory regions that are not your own (anymore) (cf, this great post) . Instead, you will leak memory when you loose the reference to a block of dynamically allocated memory. For example:

/* allocate some memory */
int *a = malloc(40);
/* reassign a without free-ing the memory before : you now have leaked memory */
a = malloc(40);

The best option is not having two pointers, pointing to the same place, which are freed independently.
But if that's really what you need, then you need a reference count.

The following code implements a very simple reference count mechanism.
When you assign a second pointer to your data, you should use clone_x to increment the reference count.
Each time you free, use free_x , and it will free just once.

Note that this code isn't multithread-safe. If your code is multi-threaded, you need atomic operations, and you need to be very careful with how you use them.

struct x {
    int refcount;
    int payload;
};
struct x *create_x(int payload) {
    struct x *newx = malloc(sizeof(*newx));
    if (!newx) return NULL;
    newx->payload = payload;
    newx->refcount = 1;
    return newx;
}
void clone_x(struct x *myx) {
    myx->refcount++;
}
void free_x(struct x *oldx) {
    oldx->refcount--;
    if (oldx->refcount == 0) {
         free(oldx);
    }
}

You can't. When free(a) is called it is no longer safe to access that memory.

Even if you malloc() new memory and assign the result to a , that memory could be anywhere.

What you're trying to do will not work.

每个分配的内存块都应有一个“所有者”,a或b,如果a是所有者,则指针b不应释放该块,反之亦然。

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