Skip to content
Advertisement

How can I get a guarantee that when a memory is freed, the OS will reclaim that memory for it’s use?

I noticed that this program:

#include <stdio.h>

int main() {
  const size_t alloc_size = 1*1024*1024;
  for (size_t i = 0; i < 3; i++) {
    printf("1n");
    usleep(1000*1000);
    void *p[3];
    for (size_t j = 3; j--; )
      memset(p[j] = malloc(alloc_size),0,alloc_size); // memset for de-virtualize the memory
    usleep(1000*1000);
    printf("2n");
    free(p[i]);
    p[i] = NULL;
    usleep(1000*1000*4);
    printf("3n");
    for (size_t j = 3; j--; )
      free(p[j]);
  }
}

which allocates 3 memories, 3 times and each time frees different memory, frees the memory according to watch free -m, which means that the OS reclaimed the memory for every free regardless of the memory’s position inside the program’s address space. Can I somehow get a guarantee for this effect? Or is there already anything like that (like a rule of >64KB allocations)?

Advertisement

Answer

The short answer is: In general, you cannot guarantee that the OS will reclaim the freed memory, but there may be an OS specific way to do it or a better way to ensure such behavior.

The long answer:

  • Your code has undefined behavior: there is an extra free(p[i]); after the printf("2n"); which accesses beyond the end of the p array.

  • You allocate large blocks (1 MB) for which your library makes individual system calls (for example mmap in linux systems), and free releases these blocks to the OS, hence the observed behavior.

  • Various OSes are likely to implement such behavior for a system specific threshold (typically 128KB), but the C standard gives guarantee about this, so relying on such behavior is system specific.

  • Read the manual page for malloc() on your system to see if this behavior can be controlled. For example, the C library on Linux uses an environment variable MMAP_THRESHOLD to override the default setting for this threshold.

  • If you program to a Posix target, you might want to use mmap() directly instead of malloc to guarantee that the memory is returned to the system once deallocated with munmap(). Note that the block returned by mmap() will have been initialized to all bits zero before the first access, so you may avoid such explicit initialization to take advantage of on demand paging, on perform explicit initialization to ensure the memory is mapped to try and minimize latency in later operations.

User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement