从 mremap 分段错误中释放内存

Freeing memory from mremap segmentation faults

通过 mremap(2) 更改的内存释放规则是什么?实验表明,如果传递给 mremap() 的地址与返回的地址相同,则 free() 将起作用。但是如果返回的地址不同,free()就会产生段错误。例如,

#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;
}

除非

否则会出现段错误

如果答案是不使用 memalign 函数族而是 mmap 匿名内存,您能否指出说明是这种情况的手册页或类似内容?

免费来自手册页 (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.

基本上,在不是由 malloc 系列分配的内存上使用 free 是未定义的。由于您使用 mremap 作为分配内存的最后一个函数,因此它不是 malloc 分配的内存。

你必须在mremap之后在这里使用munmap。此外,您不应该将 malloc 系列与 mmap 系列混合使用。那只是灾难的根源。