Is calloc better than malloc?



我刚刚在前几天了解了C calloc()功能。在阅读了其描述以及它与malloc(1,2)的不同之后,我想到,作为一个非安装程序员,我应该始终始终使用 calloc()。但这真的是这样吗?

我拥有的一个预订是访问calloc() -ED内存的额外延迟,但是我也想知道是否有情况从malloc()转换为calloc()会以某种更严重的方式打破程序。

p。S. calloc()的零启动方面对我来说很清楚。我想了解的是calloc()malloc()- calloc()提供的懒惰内存分配之间的另一个区别。如果您要纯粹专注于内存初始化方面,请不要发布答案。

这确实是一个与情况有关的决定。经验法则是

  • 如果您是第一次写入分配的内存,则malloc()更好(较少的开销)。

    示例:考虑以下方案

    char * pointer = NULL;
    //allocation
    strcpy(pointer, source);
    

    在这里,使用malloc()

  • 分配很好
  • 如果有可能使用分配的内存来读取纸,请在初始化内存时进行calloc()。这样,您可以避免使用读取未定义行为的读取前后记忆的问题。

    示例:

    char * pointer = NULL;
    //allocation
    strcat(pointer, source);
    

    在这里, strcat()已经需要第一个参数为a string ,并且使用malloc()分配无法保证。当calloc()零启动内存时,它将在此处达到目的,因此,calloc()是该情况的方法。

详细说明了第二种情况,引用了C11,第§7.24.3.1章(遵循我的重点))

strcat()功能附加了s2指向字符串的副本(包括 将null字符终止)到字符串的末端,由s1 指向。初始字符 s2的覆盖在s1末尾的空字符。[....]

因此,在这种情况下,目标指针应为字符串的指针。通过calloc()分配可以保证,在使用malloc()分配的同时,众所周知,从第7.22.3.4章

中保证这一点

malloc功能分配了一个大小由size指定的对象和 其值不确定。


编辑:

calloc()上建议malloc()的一种可能方案是编写用于单元/集成测试的测试存根。在这种情况下,使用calloc()可以隐藏潜在的错误,这些错误与以后的情况相似。

malloccalloc之间的主要区别是calloc将零启动您的缓冲区,malloc将使内存不可分化。

这将到达" 不用您不使用"的常见编程成语。换句话说,为什么如果您不一定需要(尚)()零命名的东西(有成本)?

作为旁注,因为您标记了C :使用new/delete的手动存储器使用在现代C 中皱眉(在极少数记忆池等情况下除外)。malloc/free的使用更加罕见,应该很少使用。

使用calloc进行零填充分配,但只有在真正需要零填充时。

您应该始终使用calloc(count,size)而不是buff=malloc(total_size); memset(buff,0,total_size)

调用零-memset是关键。malloccalloc都被翻译成OS调用,这些呼叫可进行大量优化,尽可能使用硬件技巧等。但是,memset几乎没有OS可以做的。

另一方面,您何时需要零填充分配的内存?唯一的常用用途是用于零端任意长度元素,例如c串。如果是这样,可以肯定的是,使用calloc

但是,如果您分配元素是固定长度或随身携带任意元素的长度(例如C 字符串和向量)的结构,则零填充根本无济于事,如果您尝试依靠它,它可能导致棘手的错误。

假设您编写自定义链接列表,并决定通过用calloc分配存储器来跳过指向下一个节点的零。它运行良好,然后有人将其与自定义位置使用新的,这不是零填充。麻烦是,有时它将是零填充的,并且可以通过所有通常的测试,进行生产,那里会崩溃,有时会崩溃,可怕的不可重复的错误。

出于调试目的,零填充通常也不是那么好。0太常见了,您很少能写出诸如assert(size);之类的东西,因为它通常也是有效的值,您也可以使用if(!size)来处理它,而不是主张。在调试器上,它也不会引起您的注意,您的记忆中通常都有零。最好的做法是避免长度的未签名类型(签名长度对于运行时错误处理和一些最常见的溢出检查也很有用)。因此,虽然要避免使用buff=malloc(total_size); memset(buff,0,total_size),但可以:

const signed char UNINIT_MEM=MY_SENTINEL_VALUE;
buff=malloc(total_size);
#if DEBUG_MEMORY
memset(buff,UNINIT_MEM,total_size);
#endif

在调试模式下,运行时库甚至OS有时会为您执行此操作,例如,在VC 上查看此出色的帖子 - 特定的Sentinel值。

这一切都与您要使用内存有关的一切。malloc返回非初始化(甚至可能还没有真实的)内存。calloc返回真实,零内存。如果您需要它为零,那么是,calloc是您的最佳选择。如果您不这样在C代码中,而不是Calloc()。

对" malloc"的文本搜索将错过calloc()呼叫。

替换库通常具有mymalloc(),myrealloc(),myfree(),而不是mycalloc()。

零的指针和真实量的零限化实际上不能保证具有预期效果,尽管在每个主要平台上,所有位零零都为零,而对于真实的指针为0.0。

calloc()倾向于隐藏错误。Debug malloc通常设置诸如DeadBeef之类的填充模式,该模式评估为较大的负数,看起来不像真实数据。因此,该程序迅速崩溃,并在调试器中被淘汰。

相关内容

  • 没有找到相关文章

最新更新