46

I would like to check if a pointer is freed already or not. How do I do this using gnu compiler set?

Raedwald
  • 46,613
  • 43
  • 151
  • 237
Kitcha
  • 1,641
  • 6
  • 19
  • 20
  • 6
    I don't think you can (at least not in a portable manner). – NPE Nov 28 '11 at 19:01
  • 7
    Suppose there *were* a way to do this. Suppose also that a pointer `p` was freed, and then another block `q` was allocated that occupied the same place in memory. What would `isFreed(p)` return? Would that be different from `isFreed(q)`? How could it be different, if `p == q`? – Greg Hewgill Nov 28 '11 at 19:06
  • @DavidHeffernan, I will take care of it. Thanks for your reminder. – Kitcha Nov 28 '11 at 19:11

9 Answers9

61

You can't. The way to track this would be to assign the pointer to 0 or NULL after freeing it. However as Fred Larson mentioned, this does nothing to other pointers pointing to the same location.

int* ptr = (int*)malloc(sizeof(int));
free(ptr);
ptr = NULL;
Chad
  • 19,219
  • 4
  • 50
  • 73
  • 1
    Is it good practice to assign values to pointers that are freed by the system? What if the system has assigned them to another pointer? – Janman Feb 14 '14 at 07:42
  • 9
    I think you have not understood the meaning of assign a NULL value to the pointer. When you do this you are cleaning up the address stored in the pointer, not the content of the address stored in the pointer. This is a good practice because it prevents the already freed pointer to be used further, what can cause security issues. – Jorge Gabriel Siqueira Jan 26 '16 at 18:28
36

You can't. Just assign NULL to it after you free it to make sure you don't free it twice (it's ok to free(NULL)).

Better yet, if possible don't write code where you "forget" you already freed it.

EDIT

Interpreting the question as how to find out whether the memory pointed to by a pointer is freed already: you can't do it. You have to do your own bookkeeping.

Community
  • 1
  • 1
cnicutar
  • 178,505
  • 25
  • 365
  • 392
  • Of course, assigning a pointer to NULL does nothing to other pointers pointing to the same allocation. Those still dangle. – Fred Larson Nov 28 '11 at 19:03
  • 2
    That's sort of sidestepping the question, though. Giving the OP the benefit of the doubt and interpreting the question as "whether the memory pointed to by a pointer is freed already" (you don't free pointers, only memory), then the question becomes "how to tell whether a given pointer value points to freed memory". – Kerrek SB Nov 28 '11 at 19:03
19

There is no reliable way to tell if a pointer has been freed, as Greg commented, the freed memory could be occupied by other irrelevant data and you'll get wrong result.

And indeed there is no standard way to check if a pointer is freed. That said, glibc does have functions (mcheck, mprobe) to find the malloc status of a pointer for heap consistency checking, and one of them is to see if a pointer is freed.

However, these functions are mainly used for debugging only, and they are not thread-safe. If you are not sure of the requirement, avoid these functions. Just make sure you have paired malloc/free.


Example http://ideone.com/MDJkj:

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

void no_op(enum mcheck_status status) {}

int main()
{
    mcheck(&no_op);

    void* f = malloc(4);

    printf("%d (should be %d)\n", mprobe(f), MCHECK_OK);
    printf("%d (should be %d)\n", mprobe(f), MCHECK_OK);

    free(f);

    printf("%d (should be %d)\n", mprobe(f), MCHECK_FREE);
    printf("%d (should be %d)\n", mprobe(f), MCHECK_FREE);

    return 0;
}
Community
  • 1
  • 1
kennytm
  • 510,854
  • 105
  • 1,084
  • 1,005
  • Thanks for the help. I want to do this while debugging with gdb from a core file, unfortunately I cannot call functions! But, maybe I can look at the source and find out how mcheck and mprobe work. – Sam Watkins Feb 21 '12 at 06:58
  • Weirdly enough, I get a `SIGABRT` if I try and `mprobe` the status of a freed variable, but only if I use `-lmcheck`. If I set it up using `mcheck` I don't get a SIGABRT. Unfortunately outside of my little test program, I can't use the `mcheck()` option because Qt seems to be injecting some kind of heap allocation before even the first line of main(), somehow). – jrh May 12 '20 at 14:27
9

You can extend the concept of assigning NULL to the pointer value by writing a macro that does it for you. For example:

#define FREE(ptr) do{ \
    free((ptr));      \
    (ptr) = NULL;     \
  }while(0)

Then as long as you make sure your code only uses FREE() and not free(), you can be fairly confident that code you wrote doesn't free the same memory twice. Of course that does nothing to prevent multiple calls into library functions that free memory. And it does nothing to guarantee that there's a free for every malloc.

You can attempt this with a function, but it gets akward because you have to throw in a reference operator and it doesn't look like a normal call to free() anymore.

Brian McFarland
  • 9,052
  • 6
  • 38
  • 56
2

I know that this answer is a little bit late, but I just read this answer and wrote some code to verify the following:

Free will put the memory block in its own free block list. Normally it also tries to meld together adjacent blocks in the address space. The free block list is just a circular list of memory chunks which have of course some admin data in the beginning. The free-list is also the first location, malloc looks for a new chunk of memory when needed. It is scanned before it calls for new memory from the OS. When a chunk is found that is bigger then the needed memory, it is just divided into two parts. One is returned to caller, the other is put back into the free list.

This code checks only if the first pointer that was allocated is freed:

int is_freed(void *p)
{
    void * q;
    char p_addr [50];
    char q_addr [50];

    sprintf(p_addr, "%p", p);

    q = malloc (1);
    sprintf(q_addr, "%p", q);
    free (q);

    return ! strcmp(q_addr, p_addr);
}

I've tested this code on HP-UX and Linux Redhat and it works, for the case of only one pointer.

Community
  • 1
  • 1
Mansuro
  • 4,558
  • 4
  • 36
  • 76
  • It is a nice idea, but I've tried here and it doesn't work. I guess it is too experimental to be used productively. (System: debian gnu linux with gcc, no optimization, pthread program). Better option still: as soon as you free it, assign it a NULL. – DrBeco Dec 03 '17 at 01:09
2

You do not, since you cannot.

Keep track of pointers that you obtain from malloc() and only free those, and only once.

If you will, memory has no memory, so it doesn't know whether it is allocated or not. Only your OS's memory manager can tell you that (but C does not include any standardized mechanism to query this information).

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
0

A friendly note: If you are setting a pointer parameter to NULL in another function and wish to have that affect the argument (original pointer passed in), the function would have to accept a pointer to that poiner (double ptr).

For example,

void cleanup(int *int_ptr) {
  free(int_ptr);
  int_ptr = NULL; // Not working ??
}

int main() {
  int a = 8; 
  int* a_ptr = &a;
  cleanup(a_ptr);
  printf("%p", a_ptr); // Unexpected: Does not print NULL
}

This doesn't work as expected. Rationale: a_ptr is a pointer, but it's really just a variable containing a value — the contained value is a little special because it is a virtual memory address, but it's a value nonetheless. When this value gets passed into cleanup, like any other variables, cleanup creates a local copy of that value. So, if a_ptr has value 0x7ffd86656848, int_ptr will also have value 0x7ffd86656848. Setting int_ptr to NULL of course does not set a_ptr to NULL.

So, if you wish to set int_ptr = NULL, you would have to pass in a double pointer.

void cleanup(int **int_ptr) {
  free(*int_ptr);
  *int_ptr = NULL;
}
Acy
  • 589
  • 2
  • 9
  • 25
-2

Write a function to catch signal SIGABRT

  • 1
    Definitely not. You can't really catch a SIGABRT: https://stackoverflow.com/questions/8934879/how-to-handle-sigabrt-signal – ocirocir Mar 03 '21 at 18:54
-3

This is how I do it:

bool pointer_allocated(void* ptr) {
  return ptr != NULL;
}

EDIT: This answer is very wrong, so I will correct it

If you want to check if the pointer is de-allocated, you can just set the pointer to NULL after freeing it.

free(ptr);
ptr = NULL;

// You can use ptr != NULL or ptr != 0, its pretty much the same thing
if(ptr) {
    // Pointer is set
} else {
    // Pointer has been freed
}

If you aren't going to use the pointer again, you don't need to set the pointer to NULL. In that case there's no point and it just wastes CPU time.

Josua Robson
  • 35
  • 1
  • 7