6

我们使用 malloc() 在 C 中动态分配内存,并接收到指向堆中某个位置的指针。现在我们使用 free() 来释放内存,传递与其 argumnet 相同的指针值。

现在的问题是 free() 如何知道要释放多少......考虑到我们总是可以调整 malloc() 分配的内存块的大小。

这里有什么与哈希表相关的吗?

4

5 回答 5

5

一个典型的实现将在 malloc 返回的地址之前存储信息。该信息将包括 realloc 或 free 需要知道的信息以完成他们的工作,但具体存储在那里的详细信息取决于实现。

于 2013-05-03T04:29:42.743 回答
4

最初的技术是分配一个稍大的块并在开始时存储大小,这是应用程序没有看到的部分。额外的空间包含一个大小,并可能链接到将空闲块连接在一起以供重用。

然而,这些技巧存在某些问题,例如糟糕的缓存和内存管理行为。在块中正确使用内存往往会不必要地对内容进行分页,并且还会创建脏页,从而使共享和写时复制变得复杂。

所以更高级的技术是保留一个单独的目录。还开发了异乎寻常的方法,其中内存区域使用相同的二次幂大小。

一般来说,答案是:分配一个单独的数据结构来保持状态。

于 2013-05-03T04:40:51.500 回答
2

一个简单的实现是著名的K&R C 圣经,第 186 - 188 页中的实现。

我们实际得到的内存块(结构头或联合头的大小)比我们申请的要多。结构可能是这样的:

typedef long Align;

union header
{
    struct 
    {
        union header* ptr;  // next block
        unsigned size;      // size of this block , times of head size  
    }s;
    Align x;
};

一个图来证明它:

在此处输入图像描述

当我们调用free函数时,行为可能是这样的:

void free(void* ptr)
{
    Header *bp, *p;

    bp = (Header *)ptr - 1;

    /* .....                */
    /*return the memory to the linked list  */
}

在visual studio中,我们有两种模型:release version而且,我们甚至可以使用head来存储调试信息,使调试更容易。调用debug versionheader ,定义如下:debug version_CrtMemBlockHeader

typedef struct _CrtMemBlockHeader
{
    struct _CrtMemBlockHeader * pBlockHeaderNext;
    struct _CrtMemBlockHeader * pBlockHeaderPrev;
    char *                      szFileName;
    int                         nLine;
    size_t                      nDataSize;
    int                         nBlockUse;
    long                        lRequest;
    unsigned char               gap[nNoMansLandSize];
} _CrtMemBlockHeader;

那么内存分配是:

在此处输入图像描述

于 2013-05-03T07:33:18.973 回答
1

内存管理器使用表来存储基于指针的附加数据,有时在指针之前,有时在其他地方。由于 C 非常简单,数据很可能是pointer-2or pointer-4, as intorlong类型。正确的细节取决于编译器。

于 2013-05-03T04:31:34.597 回答
1

当我们使用 malloc 时,一个块将获得保留,其大小将比我们请求的多一点,作为对这个 malloc 的回报,我们得到一个指向该块开始的指针。正如我告诉你的,这个块的大小将比你真正需要的多一点。这个额外的空间将用于保持实际请求的块大小、指向下一个空闲块的指针和一些检查“如果你试图访问超过分配块”。

因此,每当我们使用要解除分配的指针调用 free 时,此 free 将搜索块空间中给出的额外信息,在哪里获得最终大小以解除分配。

于 2013-05-03T05:45:00.253 回答