我已使用 malloc 和免费使用 mmap 实施。现在,由于与 free 不同, munmap 也将长度作为参数,因此我将长度作为附加信息放在映射的内存中。
我的 malloc 和免费的代码如下所示。我想问一下,如果这段代码是好的,或者我仍然遗漏任何东西或以错误的方式做某事。
void * malloc ( size_t size )
{
int *plen;
int len = size + sizeof( size ); // Add sizeof( size ) for holding length.
plen = mmap( 0, len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0 );
*plen = len; // First 4 bytes contain length.
return (void*)(&plen[1]); // Memory that is after length variable.
}
void free ( void * ptr )
{
int *plen = (int*)ptr;
int len;
plen--; // Reach top of memory
len = *plen; // Read length
munmap( (void*)plen, len );
}
答案 0 :(得分:14)
一些观察结果:
int
和size_t
具有相同的尺寸。如果你想在分配的头部存储size_t
值,那你为什么不这样做呢?为什么要介绍int
?mmap()
有很大的开销,通常分配不能小于“页面”。大多数真正的分配器试图以各种方式避免在每个malloc()
上调用操作系统级功能。mmap()
失败,则会返回MAP_FAILED
,malloc()
也是如此。因此,您需要在取消引用mmap()
返回的指针之前测试该。free(NULL)
应该是有效的事情;你的实现很可能导致崩溃,因为你没有NULL
- 在假设它有效之前检查参数。答案 1 :(得分:7)
你应该,至少。
mmap
是否失败size_t
的尺寸,而不是int
。他们可能会有所不同。int
,大概是4个字节。这意味着存储需要更大对齐的值返回内存,例如双重导致性能损失,或在某些体系结构上彻底崩溃。NULL
被传递给免费(它应该是无操作)对于malloc实现,我还希望它至少具有基本的调试支持,例如:尝试检测双重释放,尝试检测自由无效指针,列出内存不是免费的等等。
请记住,这里的malloc实现可能非常浪费。如果malloc 10个字节,你最终将分配1个页面(4096个字节),所有这些都必须映射到物理内存,剩下的4082个字节未被使用。
答案 2 :(得分:2)
另请阅读c malloc on wikipedia并仔细研究一些真正的malloc实现,例如Doug Lea's malloc。关于这个问题有很多文献,例如: by Wolfram Gloger以及许多其他人。
@MetallicPriest:你真的应该更多地解释你在做什么(我对你的工作不是很乐观,但你可能会学到很多东西!)
答案 3 :(得分:1)
每次调用自定义malloc时都不应该调用mmap。如前所述,这样做有很大的开销。
你应该创建一个大型共享内存(例如4K),你的malloc函数只需返回你所分配的内存范围内的指针。
然后,如果你的内存不足,你就会创建另外4k的共享内存。
你只需要计算你使用多少空间并跟踪你的引用,这样就可以更容易地释放内存。
答案 4 :(得分:1)
您还应该使用-1
代替0
作为mmap的fd参数。
mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
MAP_ANONYMOUS
任何文件都不支持映射;其内容初始化为零。 fd和offset参数被忽略;但是,如果指定了MAP_ANONYMOUS(或MAP_ANON),某些实现要求fd为-1,便携式应用程序应确保这一点。自内核2.4以来,Linux上仅支持将MAP_ANONYMOUS与MAP_SHARED结合使用。