我刚刚在前几天了解了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()
可以隐藏潜在的错误,这些错误与以后的情况相似。
malloc
和calloc
之间的主要区别是calloc
将零启动您的缓冲区,malloc
将使内存不可分化。
这将到达" 不用您不使用"的常见编程成语。换句话说,为什么如果您不一定需要(尚)()零命名的东西(有成本)?
作为旁注,因为您标记了C :使用new/delete
的手动存储器使用在现代C 中皱眉(在极少数记忆池等情况下除外)。malloc/free
的使用更加罕见,应该很少使用。
使用calloc
进行零填充分配,但只有在真正需要零填充时。
您应该始终使用calloc(count,size)
而不是buff=malloc(total_size); memset(buff,0,total_size)
。
调用零-memset
是关键。malloc
和calloc
都被翻译成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之类的填充模式,该模式评估为较大的负数,看起来不像真实数据。因此,该程序迅速崩溃,并在调试器中被淘汰。