What are the rules for freeing memory that has been changed via mremap(2)
? Experimentation suggests that if the address passed to mremap()
is the same one returned, then free()
will work. But if the address returned is different, free()
will produce a segmentation fault. For example,
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#define __USE_GNU
#include <sys/mman.h>
#define ALLOC_SIZE (1024 * 1024)
int
main(int argc, char *argv[])
{
void *m = NULL, *tmp;
size_t size = 4 * ALLOC_SIZE;
m = memalign(4096, size);
if (m == NULL)
return EXIT_FAILURE;
tmp = mremap(m, size, size + ALLOC_SIZE, MREMAP_MAYMOVE);
if (tmp == MAP_FAILED) {
printf("mremap(%p, %zu, %zu, MREMAP_MAYMOVE) failed\n",
m, size, size+ALLOC_SIZE);
} else {
if (tmp != m) {
printf("Memory moved from %p to %p\n", m, tmp);
m = tmp;
}
size += ALLOC_SIZE;
}
printf("Freeing %zu bytes from %p\n", size, m);
free(m);
return EXIT_SUCCESS;
}
will segfault unless
MREMAP_MAYMOVE
is removedfree
is changed to munmap
If the answer is to not use memalign
family of functions and instead mmap
anonymous memory, can you point to a man page or similar which says this is the case?
From the man page for free (man 3 free
):
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.
Basically using free on memory which is not allocated by malloc family is undefined. Since you are using mremap as the last function to allocate memory, it is not malloc allocated memory.
You have to use munmap here after the mremap. Also, you shouldn't be mixing the malloc family with mmap family. That is just a recipe for disaster.