首页 文章

动态分配的内存如何在C中保持跟踪[重复]

提问于
浏览
6

这个问题在这里已有答案:

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

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

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

5 回答

  • 2

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

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

    所以更先进的技术是保持一个单独的目录 . 还开发了外来方法,其中存储器区域使用相同的两个功率大小 .

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

  • 4

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

  • 1

    一个简单的实现是着名的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 中的 Headers 被称为 _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

  • 1

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

  • 5

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

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

相关问题