Как realloc знает, сколько копировать? - PullRequest
12 голосов
/ 13 августа 2010

откуда realloc знает размер исходных данных?

 void *realloc(void *ptr, size_t size);

Итак, если реализация выглядит так:

 temp = malloc(size);
 memcpy(.. // How much to copy?
 free(ptr);
 return temp;

Я понимаю, что это не оригинальная реализацияrealloc не всегда делает бесплатно, но когда делает, сколько копирует?

Редактировать: Спасибо за ответы.Но как я могу реализовать realloc в своем коде с помощью malloc / free /..?

Ответы [ 5 ]

19 голосов
/ 13 августа 2010

Он знает, потому что malloc записал эту информацию, когда вы ее вызвали. В конце концов, система все равно должна отслеживать размеры выделенных блоков, чтобы она не выделяла определенную область памяти дважды.

Если вы имеете в виду «как он узнает, сколько массива я написал до сих пор», это не нужно. Он также может просто скопировать любой неинициализированный мусор.

3 голосов
/ 13 августа 2010

But how can I then implement realloc in my code with malloc/free/..?

Если вы уже используете malloc & free, почему бы просто не использовать realloc? иначе вы можете просто взглянуть на источник CRT, который поставляется с MSVC / gcc и т. д. (или просто загрузить его, в случае GCC), и посмотреть, как они его реализуют. Если вы используете собственный распределитель, то это немного более ситуативно, например: я использую двоичный бин с системой типа слябов, в этом случае realloc прост:

void* Reallocate(Manager* pManager, void* pBlock, size_t nSize, const char* szFile, const DWORD dwLine)
{
    #if ( MMANAGER_NULL_TO_DEFAULT )
        if(pManager == NULL)
            pManager = MMANAGER_DEFUALT_MANAGER;
    #endif

    if(pBlock == NULL)
        return Allocate(pManager,nSize,szFile,dwLine);
    else if(nSize == 0)
    {
        Free(pManager,pBlock,szFile,dwLine);
        return NULL;
    }

    BlockHeader* pHeader = GetHeader(pBlock);
    size_t nPrevSize = pHeader->pPoolBlock->nSize;
    if(nPrevSize < nSize)
    {
        void* pNewBlock = Allocate(pManager,nSize,szFile,dwLine);
        memcpy(pNewBlock,pBlock,nPrevSize);
        PoolBlock* pPoolBlock = pHeader->pPoolBlock;
        if(pPoolBlock == NULL)
            free(pHeader);
        else
            FreeBlock(pPoolBlock,pHeader);

        return pNewBlock;
    }

    return pBlock;
}
1 голос
/ 13 августа 2010

Почему бы вам просто не посмотреть, как malloc / calloc / realloc / free реализована в используемой вами стандартной библиотеке C?

Или, если у вас нет доступа к исходному коду, посмотрите, как он реализован в одной из стандартных библиотек C с открытым исходным кодом.

1 голос
/ 13 августа 2010

Когда вы malloc используете некоторую память, блок, который вы получаете, обычно представляет собой фиксированное смещение в большую структуру данных, которая также содержит дополнительную информацию, в частности размер блока. Вы можете проверить, что это так в некоторых системах, просто отметив, что каждый адрес, возвращаемый malloc, заканчивается на 8 при печати в шестнадцатеричном формате (например, с заменой %p на printf). Конечно, realloc может изменить это смещение и вернуться к структуре управления памятью, и таким образом получить размер; оттуда, способность знать, сколько копировать (когда необходимо), тривиальна…

1 голос
/ 13 августа 2010

realloc (и malloc и free) имеют полный доступ ко всей структуре данных, которая составляет кучу.В этой структуре данных содержится информация о размерах блоков, которую realloc должна знать, и поэтому она бесплатна.

...