首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何实现calloc

如何实现calloc
EN

Stack Overflow用户
提问于 2017-10-20 16:58:21
回答 1查看 7K关注 0票数 3

我试图重写malloc和calloc,我的问题是calloc的实现,而不是如何使用它。

应该始终使用calloc()而不是malloc()+memset(),因为它可以利用copy-on-write (COW)。

一些calloc的实现方式如下:

代码语言:javascript
复制
void * calloc(size_t nelem, size_t elsize)
{
    void *p;

    p = malloc (nelem * elsize);
    if (p == 0)
        return (p);

    bzero (p, nelem * elsize);
    return (p);
}

但是他们根本不使用牛(也不检查溢出)。

如果这些实现不调用bzero(),它们必须假设它们接收到的mmap'ed页面是零填充的,它们可能是出于安全原因,我们不希望其他进程的数据泄漏,但我找不到有关这方面的任何标准引用。

不使用MAP_ANON,我们可以从/dev/zero中获取mmap

代码语言:javascript
复制
fd = open("/dev/zero", O_RDWR); 
a = mmap (0, 4096e4, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FILE, fd, 0);

但是POSIX并没有规定/dev/zero,人们可以很容易地执行sudo mv /dev/zero /dev/foo,从而破坏了我的实现。

什么是有效重写calloc()的正确方法,尊重抄写?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-10-21 10:52:08

纯POSIX不支持匿名内存映射,并且没有比calloc更低级别的接口来分配零内存。

现有的POSIX实现通过MAP_ANONMAP_ANONYMOUS标志(或者从历史上通过从/dev/zero映射)支持匿名私有内存映射作为扩展。内核确保应用程序只看到零内存。(也有一些较旧的接口,如brksbrk,但它们很难使用非线程安全的接口。)

malloc函数族的实现通常使用mmap分配更大的块,并为每个块保留一个水印指针,指示哪个部分已经分配给应用程序至少一次(通过mmap并不重要)。calloc在返回分配前检查水印指针,如果应用程序之前使用了内存,则会清除它。否则,它将直接返回,因为它知道它是新的,因此已经被内核清除。

也可以使用mmap直接分配大型块。但是内核最终也必须清除内存(在使用内存回映射触发写上复制错误之前),所以只有当分配比实际需要的要大得多时,这才是一个明显的胜利,而且大多数部分从未写入。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46853908

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档