Как `realloc` работает в фоновом режиме?

Как realloc работает в фоновом режиме? Если в старом месте недостаточно памяти это выделяет два/много блоков памяти и один указатель указывая на это, а другие связаны с каждым из них другой или старый регион, скопированный на новое место, где достаточно доступна память и указатель обновляется до нового адреса и удаляет старую память?

И есть ли realloc зависимый или независимый от компилятора/ОС?

Ответ 1

realloc пытается расширить доступный диапазон памяти, если в куче имеется достаточное количество памяти. Если нет, то это эквивалентно malloc блоку нового размера, memcpy ваше содержимое там, free старый блок. Это не зависит от ОС и компилятора и зависит от реализации libc, с которой вы ссылаетесь.

Аналогичным образом: mremap/MREMAP_MAYMOVE (доступно на современной Linux) попытается расширить ваше виртуальное сопоставление запрошенным размером. Если это невозможно, оно переместит ваше сопоставление на новый виртуальный адрес с достаточным пространством VM за ним, а затем расширит ваше сопоставление. Это очень быстро, если вы часто изменяете размер больших отображений, поскольку физическое копирование не выполняется.

Ответ 2

Реализация realloc() может выглядеть примерно так:

void * realloc(void *ptr, size_t size)
{
    // realloc() on a NULL pointer is the same as malloc().
    if (ptr == NULL)
        return malloc(size);

    size_t oldsize = malloc_getsize(ptr);

    // Are we shrinking an allocation? That easy.
    if (size < oldsize) {
        malloc_setsize(ptr, size);
        return ptr;
    }

    // Can we grow this allocation in place?
    if (malloc_can_grow(ptr, size)) {
        malloc_setsize(ptr, size);
        return ptr;
    }

    // Create a new allocation, move the data there, and free the old one.
    void *newptr = malloc(size);
    if (newptr == NULL)
        return NULL;
    memcpy(newptr, ptr, oldsize);
    free(ptr);
    return newptr;
}

Обратите внимание, что я вызываю несколько функций с именами, начинающимися с malloc_ здесь. Эти функции фактически не существуют (насколько мне известно) в любой реализации; они предназначены как заполнители, однако распределитель фактически выполняет эти задачи внутри страны.

Поскольку реализация realloc() зависит от этих внутренних инструментов, ее реализация зависит от ОС. Однако интерфейс realloc() универсален.

Ответ 3

Если старый указатель не может быть изменен на месте, где будет выделен новый, содержимое будет скопировано, а старый будет освобожден.