如何在C中跟踪动态分配的内存

时间:2013-05-03 04:27:02

标签: c memory

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

现在的问题是free()如何知道取消分配多少...考虑到我们总是可以调整malloc()分配的内存块的事实。

这里有与哈希表相关的内容吗?

5 个答案:

答案 0 :(得分:5)

典型的实现将在malloc返回的地址之前存储信息。该信息将包括重新分配或免费需要知道的信息以进行其工作,但具体存储的详细信息取决于实施。

答案 1 :(得分:4)

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

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

因此,更高级的技术是保留一个单独的目录。还开发了外来方法,其中存储区域使用相同的两种功率。

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

答案 2 :(得分:2)

简化的实现是着名的K&R C Bible,第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;
};

一个证明它的图:

enter image description here

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

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

    bp = (Header *)ptr - 1;

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

在visual studio中,我们有两个模型:release versiondebug version,我们甚至可以使用 头部存储调试消息以使调试更容易。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;

然后记忆lalout是:

enter image description here

答案 3 :(得分:1)

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

答案 4 :(得分:1)

当我们使用malloc时,一个块将获得保留,其大小将比我们请求的更多,并且为了返回这个malloc,我们得到一个指向该块的开始的指针。 我告诉你这个块的大小将比你需要的更多。这个额外的空间将用于保持实际请求的块大小,指向下一个空闲块的指针以及一些检查“如果你试图访问多于分配块“。

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