9

I've read this question and answer: How do malloc() and free() work?

A friend asked me how can I be sure a free worked. I replied that if it didn't work then the OS is probably crashing and it won't matter for much longer.

But I'm more interested in the nature of the answer to this question. Once I've freed memory how can I be sure it has been freed? Do I just assume it did? This is a purely theoretical question with no actual code behind it, and mostly when thinking about I decided "well it doesn't matter anyway", but I'm uneasy with this answer.

For instance if memory is a problem and I want to make sure that a large structure was freed after calling free, otherwise I'll try cleaning up again, is there a way to do this?

Edit: To those stating my question answered here: Function free() in C isn't working for me The answer provided there simply states that I "cannot actually test if free() worked". I'm trying to understand why this cannot be done. What is the nature behind free.

Edit2: After reading through the answers provided it seems that the answer I gave my friend is accepted, that "it just works".

mrflash818
  • 930
  • 13
  • 24
Blue Granny
  • 772
  • 1
  • 8
  • 24
  • Computers are deterministic, there is no other possible outcome for a call to `free()` than to free the memory... Unless the heap is corrupted or the computer broken. – alain Dec 06 '16 at 15:55
  • 2
    Possible duplicate of [Function free() in C isn't working for me](http://stackoverflow.com/questions/7774443/function-free-in-c-isnt-working-for-me) – Alex K. Dec 06 '16 at 15:56
  • Freeing a large structure may involve multiple calls to free as different parts of the structure may have been allocated separately. – chqrlie Dec 06 '16 at 16:06
  • 1
    Note that freeing memory normally only releases it into the free memory pool that `malloc()` and friends can reuse. It usually does not release the memory back to the o/s. Thus the total amount of memory used by your program usually doesn't decrease just because you freed some memory. – Jonathan Leffler Dec 06 '16 at 16:54
  • 1
    @Rakesh_K: If you are asking whether the freed memory is altered, the most common answer is "no" but the memory management functions could use the freed memory for their own purposes, and some debugging allocators do deliberately overwrite the freed memory so that you can tell if some of your code is trying to access the freed memory after it was freed. You cannot rely on it being unchanged. – Jonathan Leffler Dec 06 '16 at 17:05
  • 1
    If one is entertaining the possibility that a conforming call to `free()` doesn't behave as documented, as the OP seems to be doing, then one is postulating that the `free()` implementation may be buggy. I'm inclined to agree with the OP's initial assessment: if you cannot rely on `free()` then you're toast. Except for the purpose of testing and maintaining the system's C standard library itself, there's no point in even considering the possibility. – John Bollinger Dec 06 '16 at 17:17
  • @AlexK. The question you've linked doesn't explain the essence behind the anwer I'm trying to find, rather states that "you cannot actually test if free() works". I'm trying to understand the why. – Blue Granny Dec 06 '16 at 19:46

5 Answers5

8

The only way free "doesn't work" is if you pass it an invalid pointer or one that's already been freed. Doing so invokes undefined behavior.

From the man page:

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 run your program under a memory checking tool like valgrind, it will tell you if you're calling free incorrectly.

dbush
  • 205,898
  • 23
  • 218
  • 273
  • I've read the man page and read through the answers given to the question I linked in my question. I'm asking how can I be sure that if I've called free, a call to malloc will give me that space I freed (for arguments sake let's say that I've freed the only memory available). I recognize the workaround of checking if the malloc worked in this case, as I stated the use case isn't easy for me to see, rather I'm fighting to understand the nature of free. – Blue Granny Dec 06 '16 at 19:51
  • @ArikRinberg There's no guarantee that `malloc` will return a memory block that was previously passed to `free`, and even if it does it doesn't tell you anything. If you want to know how `malloc` and `free` work under the hood, look at the Linux source. – dbush Dec 06 '16 at 19:54
  • @ArikRinberg Even then, other operating systems may implement `malloc` and `free` entirely differently from Linux. – dbush Dec 06 '16 at 19:55
  • Which is why I was careful in stating that I recognize the workaround. From what I'm understanding from your answering you're basically stating that free() works because it can't not work. That is the answer I'm finding difficult to accept. – Blue Granny Dec 06 '16 at 19:56
  • 1
    @ArikRinberg That's pretty much it. The function has a precondition (namely that the given pointer was returned by `malloc` and family). If that precondition is met, then the function will always do the right thing, as it knows what its internal data structures are and how to manage them. Otherwise, the function has a bug (unlikely). – dbush Dec 06 '16 at 20:04
5

if memory is a problem and I want to make sure that a large structure was freed after calling free, otherwise I'll try cleaning up again, is there a way to do this?

No, there is no legal way to free the same memory twice. In fact, calling free on a freed pointer leads to undefined behavior. That is why you should set freed pointers to NULL if they are to remain in scope.

There is also no API to see if a memory address has been freed or not, so your code must keep track of what is currently allocated in order to free it at some later point.

You can only do so much returning the memory to the operating system: once you call free, it's out of your hands, so you need to rely on the OS and on the memory manager of your C library to account for the freed memory correctly.

The best you can do on your side is to run your code through a memory profiler under its typical workload, and fix all errors.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
4

free does not return any value, or set errno to be anything (barring whatever implementation-specific features your compiler might have). The documentation for free says:

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 call free on memory that was not allocated using the malloc family of functions, the result is undefined. If your program crashes on calling free (or operator delete in C++), it's a sign of poor memory management elsewhere in your code.

Govind Parmar
  • 20,656
  • 7
  • 53
  • 85
3

You cannot verify it for specific memory allocation. There is no system call to ask if an allocation is still allocated or has already been freed.

However, as memory management and in particular memory leaks (allocations not freed), references to already freed memory, double frees and memory corruption are a serious issue in all programming languages with explicit memory management, there are tools to debug these kind of problems, such as Purify, Insure++, Valgrind or Boundschecker.

Codo
  • 75,595
  • 17
  • 168
  • 206
0

as mentioned above free doesn't return any value but just to verify I initialized one of the members from the structure & printed it before and after using free.(FYI- this is just an experiment)

struct BookList {
int BookNumber;
char BookName[4];
struct BookList * ptr_next;
}BookListVar,*ptr_BookList;

ptr_current = (struct ptr_BookList *)malloc(sizeof(struct BookList)); 
ptr_current->BookNumber = 123;
printf("BookNumber Stored : %d\n", ptr_current->BookNumber);  //got 123 as output
free(ptr_current);
printf("BookNumber Stored : %d\n", ptr_current->BookNumber);  //Got some garbage value
Govind Parmar
  • 20,656
  • 7
  • 53
  • 85
OPat
  • 1
  • 2
  • 3
    Hopefully this was just to experiment - trying to access memory that is not allocaded is probably inflicting undefined behaviour. Moreover, I am pretty sure that free does not need to overwrite or alter freed mem chunks in any way. Thus this test is dangerous and highly unreliable. – Michael Beer Jun 16 '18 at 01:31