-2

Possible Duplicate:
How do malloc() and free() work?

I have encountered a weird problem and I'm really not sure why it doesn't work.

I have the following code in Xcode:

void *ptr = malloc(1024 * 1024 * 100);
memset(ptr, 0, 1024 * 1024 * 100);
free (ptr); //trace this line
ptr = malloc (1024 * 1024 * 100);
memset(ptr, 0, 1024 * 1024 * 100);
free (ptr); //trace this line

I put a breakpoint on each of the free() line, and when I traced the program, free didn't really free up the 100mb. However, if I change the number from 100 to 500 (allocate 500mb twice), memset 500mb, free() works fine. Why?

Community
  • 1
  • 1
Josh
  • 692
  • 2
  • 9
  • 38
  • 3
    `free()` always "works fine". What's wrong is your *expectation* of what it should do. – Kerrek SB Jan 22 '13 at 15:39
  • Is this objective C or C? – djechlin Jan 22 '13 at 15:40
  • How can you assert that memory is not free'd up? – Paolo Jan 22 '13 at 15:40
  • If you are expecting the value of `ptr` to be `NULL` after calling `free()`, then you have got the wrong idea. – Graham Borland Jan 22 '13 at 15:41
  • 2
    http://stackoverflow.com/questions/1119134/how-do-malloc-and-free-work?rq=1 – djechlin Jan 22 '13 at 15:42
  • You don't seem to understand how allocation works. If that's the case, you can't assume that "it doesn't work". – netcoder Jan 22 '13 at 15:50
  • I monitored my memory using vm_stat and after free() finished executing it doesn't free up the memory that I allocated. Again if I allocate 500 each then free those 500mb (500mb x 2) it works fine. – Josh Jan 22 '13 at 16:13
  • @Jerry Coffin now I understand free doesn't mean returning memory to the OS (I'm using MAC OS X). One more question though, when I allocate 500mb twice then deallocate them, it returns to the OS immediately, but when I allocate 100mb twice it doesn't return to the OS, why is that? – Josh Jan 22 '13 at 16:46
  • @Jerry Coffin thanks again for your help :), how can I give you a vote? – Josh Jan 22 '13 at 17:06
  • @Josh: I've put the info into an answer. – Jerry Coffin Jan 22 '13 at 18:19

4 Answers4

2

free can never fail(it does not have a return value) unless you call it with a improper address, which gives you undefined behavior.

You do not have to bother whether free actually frees memory or not you just have to ensure that you call free on the correct address after you are done with dynamic memory usage, rest the compiler should take care for you.
This is one of those things that you should just believe on your compiler to handle correctly.

Also, free just marks the memory being deallocated free(as name says) for reuse. It does not zero out or initialize the memory being deallocated.

Alok Save
  • 202,538
  • 53
  • 430
  • 533
0

free() does not have to immediately unmap and return to the OS the pages backing up previously but no longer allocated buffers. It may keep them around so you can allocate memory quickly again. When the program finishes, the pages will be unmapped and returned to the OS.

Alexey Frunze
  • 61,140
  • 12
  • 83
  • 180
0

As others already said, free() doesn't have to return memory to the OS. But I reject an idea that you should never care whether the memory is returned. There should be a good reason to care, but there are valid reasons.

If you do want to return memory to OS, use a platform-specific way which provides this guarantee:

  1. mmap with MAP_ANONYMOUS on systems supporting it (there are many, but MAP_ANONYMOUS is not POSIX): mmap instead of malloc, munmap instead of free.

  2. VirtualAlloc and VirtualFree on Windows.

[Shoul I add something here for other systems? Feel free to suggest.]

These ways of allocating memory work with big memory units (system page size or more).

Anton Kovalenko
  • 20,999
  • 2
  • 37
  • 69
0

When you pass a block of memory to free, that memory does not necessarily get returned to the operating system right away. In fact, based on the wording in the C standard, some argue that the memory can't be returned to the OS until the program exits.

The wording in question is (C99, §7.20.3.2/2): "The free function causes the space pointed to by ptr to be deallocated, that is, made available for further allocation." Their argument is that when/if a block of memory is allocated and then freed, it should be available for allocation again -- but if it's returned to the OS, some other process might take it, so it's no longer available for further allocation, as the standard requires. Personally, I don't find that argument completely convincing (I think "allocated by another process" is still allocation), but such is life.

Most libraries allocate large chunks of memory from the OS, and then sub-allocate pieces of those large chunks to the program. When memory is freed by the program, the put that block of memory on an "available" list for further allocation. Most also (at least at times) walk through the list of free blocks, merging free blocks that are adjacent addresses.

Many also follow some heuristics about what memory to keep after it's been freed. First, the keep an entire block as long as any of the memory in that block remains in use. If, however, all the memory in a block has been freed, they look at its size, and (often) at how much free memory they have available. If the amount available and/or size of the free block exceeds some threshold, they'll usually release it back to the OS.

Rather than having fixed thresholds, some try to tailor their behavior to the environment by (for example) basing their thresholds on percentages of available memory instead of fixed sizes. Without that, programs written (say) ten years ago when available memory was typically a lot smaller would often do quite a bit of "thrashing" -- repeatedly allocating and releasing the same (or similar) size blocks to/from the OS.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111