как перевыделение знает размер исходных данных?
void *realloc(void *ptr, size_t size);
Так, если реализация похожа на это:
temp = malloc(size);
memcpy(.. // How much to copy?
free(ptr);
return temp;
Я понимаю, что это не исходная реализация, и перевыделение не всегда делает свободный, но когда это делает, сколько это копирует?
Править: Спасибо за ответы. Но как я могу затем реализовать перевыделение в своем коде с malloc/free/..?
Он знает, потому что malloc
записывал эту информацию, когда вы ее вызывали. В конце концов, система в любом случае должна отслеживать размеры выделенных блоков, чтобы не выделять конкретную область памяти дважды.
Если вы имеете в виду, «как он узнает, какой объем массива я написал на данный момент», это не обязательно. Он также может просто копировать любой неинициализированный мусор.
realloc (и malloc, и free) имеют полный доступ ко всей структуре данных, составляющей кучу. В этой структуре данных есть информация о размерах блоков, которую необходимо знать realloc, как и free.
Когда вы malloc
некоторую память, блок, который вы получаете, обычно представляет собой фиксированное смещение в большую структуру данных, которая также содержит дополнительную информацию, особенно размер блока. Вы можете проверить, что это так в некоторых системах, просто отметив, что каждый адрес, возвращаемый malloc
, оканчивается на 8
при печати в шестнадцатеричном формате (например, с % p
] заменой на printf
). Конечно, realloc
может изменить это смещение и вернуться к структуре управления памятью, и таким образом получить размер; оттуда легко узнать, сколько копировать (при необходимости)…
Но как мне потом реализовать realloc в моем коде с malloc/free/...?
Если вы уже используете malloc и free, почему бы просто не использовать realloc? В противном случае вы можете просто взглянуть на исходники CRT, которые поставляются с MSVC/gcc и т.д. (или просто скачать его, в случае GCC), и посмотреть, как они это реализуют. Если вы используете собственный аллокатор, то это более ситуативно, например: Я использую бинарный бин с системой типов slab, в этом случае перераспределение простое:
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;
}
Почему бы вам просто не посмотреть, как malloc / calloc / realloc / free реализован в стандартной библиотеке C, которую вы используете?
Или, если у вас нет доступа к исходному коду, посмотрите, как это реализовано в одной из стандартных библиотек C.