这个问题在这里已有答案:
我们使用malloc()在C中动态分配内存,并且我们收到指向堆中位置的指针 . 现在我们使用free()来释放内存,传递与argumnet相同的指针值 .
现在的问题是free()如何知道取消分配多少...考虑到我们总是可以调整malloc()分配的内存块的事实 .
这里有什么与哈希表相关的东西吗?
最初的技术是分配一个稍大的块并在开头存储大小,这是应用程序没有看到的部分 . 额外的空间包含一个大小,并且可能链接到将空闲块连接在一起以便重用 .
但是,这些技巧存在某些问题,例如缓存和内存管理行为不佳 . 在块中使用内存往往会不必要地对页面进行分页,并且还会创建脏页面,这使得共享和写入时复制变得复杂 .
所以更先进的技术是保持一个单独的目录 . 还开发了外来方法,其中存储器区域使用相同的两个功率大小 .
一般来说,答案是:分配一个单独的数据结构来保持状态 .
典型的实现将在malloc返回的地址之前存储信息 . 该信息将包括重新分配或免费需要知道的信息以进行其工作,但具体存储的详细信息取决于实施 .
一个简单的实现是着名的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; };
一个图来证明它:
当我们调用 free 函数时,行为可能如下所示:
free
void free(void* ptr) { Header *bp, *p; bp = (Header *)ptr - 1; /* ..... */ /*return the memory to the linked list */ }
在visual studio中,我们有两个模型: release version 和 debug version ,我们甚至可以使用头来存储调试消息以使调试更容易 . debug version 中的 Headers 被称为 _CrtMemBlockHeader ,定义如下:
release 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是:
内存管理器使用表来存储基于指针的附加数据,有时在指针之前,有时在其他地方 . C非常简单,数据很可能是 pointer-2 或 pointer-4 ,如 int 或 long 类型 . 正确的细节取决于编译器 .
pointer-2
pointer-4
int
long
当我们使用malloc时,一个块将获得保留,其大小将比我们请求的更多,并且为了返回这个malloc,我们得到一个指向该块的开始的指针 . 我告诉你这个块的大小将比你需要的更多 . 这个额外的空间将用于保持实际请求的块大小,指向下一个空闲块的指针以及一些检查“如果你试图访问多于分配块“ .
因此,每当我们使用我们想要解除分配的指针调用free时,这个free将搜索块空间中给出的额外信息,其中它获取最终大小以解除分配 .
5 回答
最初的技术是分配一个稍大的块并在开头存储大小,这是应用程序没有看到的部分 . 额外的空间包含一个大小,并且可能链接到将空闲块连接在一起以便重用 .
但是,这些技巧存在某些问题,例如缓存和内存管理行为不佳 . 在块中使用内存往往会不必要地对页面进行分页,并且还会创建脏页面,这使得共享和写入时复制变得复杂 .
所以更先进的技术是保持一个单独的目录 . 还开发了外来方法,其中存储器区域使用相同的两个功率大小 .
一般来说,答案是:分配一个单独的数据结构来保持状态 .
典型的实现将在malloc返回的地址之前存储信息 . 该信息将包括重新分配或免费需要知道的信息以进行其工作,但具体存储的详细信息取决于实施 .
一个简单的实现是着名的K&R C Bible,第186-188页 .
我们实际获得的内存块比我们申请的更多(结构头部或联合头部的大小) . 结构可能是这样的:
一个图来证明它:
当我们调用
free
函数时,行为可能如下所示:在visual studio中,我们有两个模型:
release version
和debug version
,我们甚至可以使用头来存储调试消息以使调试更容易 .debug version
中的 Headers 被称为_CrtMemBlockHeader
,定义如下:然后记忆lalout是:
内存管理器使用表来存储基于指针的附加数据,有时在指针之前,有时在其他地方 . C非常简单,数据很可能是
pointer-2
或pointer-4
,如int
或long
类型 . 正确的细节取决于编译器 .当我们使用malloc时,一个块将获得保留,其大小将比我们请求的更多,并且为了返回这个malloc,我们得到一个指向该块的开始的指针 . 我告诉你这个块的大小将比你需要的更多 . 这个额外的空间将用于保持实际请求的块大小,指向下一个空闲块的指针以及一些检查“如果你试图访问多于分配块“ .
因此,每当我们使用我们想要解除分配的指针调用free时,这个free将搜索块空间中给出的额外信息,其中它获取最终大小以解除分配 .