12

realloc 如何知道原始数据的大小?

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

所以,如果实现是这样的:

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

我意识到这不是最初的实现,并且 realloc 并不总是免费的,但是当它这样做时,它复制了多少?

编辑:感谢您的回答。但是我怎样才能在我的代码中使用 malloc/free/.. 实现 realloc?

4

5 回答 5

21

它知道是因为malloc在您调用它时记录了该信息。毕竟,系统无论如何都必须跟踪分配块的大小,这样它就不会两次分配特定的内存区域。

如果你的意思是,“它怎么知道我到目前为止写了多少数组”,它不需要。它也可以复制任何未初始化的垃圾。

于 2010-08-13T11:45:52.970 回答
3

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

如果您已经在使用 malloc 和 free,为什么不直接使用 realloc?否则你可以看一下 MSVC/gcc 等附带的 CRT 源代码(或者只是下载它,在 GCC 的情况下),看看他们是如何实现它的。如果您正在运行自定义分配器,那么它的情况会更复杂一些,例如:我使用带有平板类型系统的二进制 bin,在这种情况下 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;
}
于 2010-08-13T12:36:24.573 回答
1

realloc(以及 malloc 和 free)可以完全访问构成堆的整个数据结构。在该数据结构中是有关块大小的信息,realloc 需要知道,free 也需要知道。

于 2010-08-13T11:46:33.933 回答
1

当你malloc有一些内存时,你得到的块通常是一个更大的数据结构的固定偏移量,它还保存额外的信息,特别是块的大小。您可以在某些系统上验证这是否正确,只需注意以十六进制打印时返回的每个地址都以malloc结尾(例如,替换为)。当然,可以把这个偏移量倒过来,回到内存管理结构中,从而得到大小;从那里开始,能够知道要复制多少(必要时)是微不足道的……</p> 8%pprintfrealloc

于 2010-08-13T11:58:58.653 回答
1

您为什么不直接查看您正在使用的 C 标准库中的 malloc/calloc/realloc/free 是如何实现的?

或者,如果您无权访问源代码,请查看它是如何在开源 C 标准库之一中实现的。

于 2010-08-13T12:57:32.887 回答