将内存归零(即calloc()
超过malloc()
)有什么好处?你不会将价值改为其他东西吗?
答案 0 :(得分:16)
有两个阵营:一个表示在声明变量时初始化变量有助于发现错误。这个阵营中的人确保他们宣布的所有内容都已初始化。他们将指向NULL
,int
的指针初始化为0等等。这个想法是一切都是确定的,当他们在调试器中看到NULL
- 指针时,他们立即知道它不是设置不当。它还可以帮助您的程序在测试期间崩溃,因为NULL
- 指针解除引用而不是在生产运行中神秘地崩溃。
另一个阵营说在声明时初始化变量会使调试变得更难,因为现在编译器无法警告你“未经设置就使用”的变量。
没有告诉你我的个人偏好 1 :如果你属于第一阵营,你会想calloc()
而不是malloc()
。如果你属于第二个阵营(显然你那么做),那么你更喜欢malloc()
而不是calloc()
。
现在有两个例外:
calloc()
而是malloc()
,因为您正在初始化浮点数或指针,并且您知道所有位都不是对他们而言必然意味着0
。或者,您不需要额外的开销。calloc()
。例如,如果您想计算n
m
动态分配的int
数据的行总和。1 你可以在这里查看我对许多问题的答案,看看我属于哪个阵营: - )。
答案 1 :(得分:8)
calloc
带有指针的结构:它们被初始化为NULL。在我很久以前工作的实时过程控制系统中,我们决定让开机逻辑将所有RAM初始化为0xCC,即8086的interrupt 3
指令。这将导致处理器进入监视器(原始调试器),如果它以某种方式执行未初始化的内存。 (无益,8086快乐地执行包含零的内存,因为它们是add [bx+si],al
指令。即使是32位模式也会使它们成为add [ax],al
指令。)
我不记得我们是否找到过失控程序,但是在各种值中对应于0xCC的值:52,428(无符号16位), - 19,660(带符号16位), - 107374176(32位浮点),和-9.25596313493e + 61(64位浮点数)出现在很多意想不到的地方。此外,一些代码期望字符是7位ASCII - 也就是说,当它试图处理0xCC时,一个错误警告我们它的存在。
答案 2 :(得分:3)
假设您要编写计数排序实现,或者深度首先搜索图形并跟踪访问的顶点。您将在算法运行时更新内存(而不是只分配一次值)。您需要在开始时将其初始化为零。如果您没有calloc
,则必须手动完成它并在算法开始时将其初始化为零。 calloc
可以更有效地为您做到这一点。
答案 3 :(得分:1)
很高兴知道你分配的任何东西都被初始化为零。许多错误来自使用未初始化内存的代码。另外,结构/类中的一些默认值可能很好,因此您不需要在malloc之后更改所有值。
例如,在malloc中分配一个包含一些指针的结构。除非将它们设置为NULL,否则NULL检查并不总是有效。如果使用calloc,则不必为指针值执行额外的初始化步骤。
答案 4 :(得分:0)
除了初始化变量的好处之外,calloc还有助于追踪错误。
如果您在没有正确初始化的情况下意外使用了一些已分配的内存,应用程序将始终以相同的方式失败。例如,来自空指针的访问冲突。对于malloc,内存具有随机值,这可能导致程序以随机方式失败。
随机故障很难追踪,calloc有助于避免这些故障。
答案 5 :(得分:0)
首先,你不能使用calloc指针,至少在你想要遵循标准C时不会。
其次,当你用全零删除成员时,错误就会被掩盖。更好的做法是使用malloc的调试版本将内存初始化为总会崩溃的内容,例如0xCDCDCDCD。
然后,当您看到Access语音时,您会立即知道问题。 拥有免费调试功能也是有益的,它将以不同的模式鞭打内存,以便那些在内存释放后触摸内存的人会产生意想不到的惊喜。
在嵌入式系统上工作时,通常不能选择“确定”。你通常一次性分配和填充,所以calloc只是男人,你是双重触摸记忆。
答案 6 :(得分:0)
没有人谈到表演的方面所以我想我必须这样做。如果你需要编写一个非常快速的程序malloc,带有“以防万一”集成的memset不是一个好方法。 memset的速度无关紧要,它总是太慢。有时你必须初始化一个向量或一个数组,所以真正的问题是控制你的时钟周期(我不浪费它们)。我曾经听过一句话“你不应该意外地放弃表现”,这意味着从表现的角度来看,你必须始终知道为什么你选择以某种方式实现代码(利弊是什么以及如何权衡它们)在特定情况下彼此)。
如果你有一个用字符串填充的缓冲区,那么在填充字符串之前初始化它可能是“很好的”,但大多数人会同意它完全浪费时钟周期。如果您正在编写一个新的str *函数,您可能希望 - 出于调试目的 - 使用通常不应出现的值填充缓冲区,但这将在分发时删除。
正如其他人所提到的,如果正在访问一个未初始化的变量,编译器会发出警告,因此我认为它的底线是没有理由初始化“以防万一。”