calloc - 将内存清零的有用性

时间:2010-02-13 02:09:07

标签: c memory memory-management malloc calloc

将内存归零(即calloc()超过malloc())有什么好处?你不会将价值改为其他东西吗?

7 个答案:

答案 0 :(得分:16)

有两个阵营:一个表示在声明变量时初始化变量有助于发现错误。这个阵营中的人确保他们宣布的所有内容都已初始化。他们将指向NULLint的指针初始化为0等等。这个想法是一切都是确定的,当他们在调试器中看到NULL - 指针时,他们立即知道它不是设置不当。它还可以帮助您的程序在测试期间崩溃,因为NULL - 指针解除引用而不是在生产运行中神秘地崩溃。

另一个阵营说在声明时初始化变量会使调试变得更难,因为现在编译器无法警告你“未经设置就使用”的变量。

没有告诉你我的个人偏好 1 :如果你属于第一阵营,你会想calloc()而不是malloc()。如果你属于第二个阵营(显然那么做),那么你更喜欢malloc()而不是calloc()

现在有两个例外:

  • 如果您属于“初始化所有”阵营,则不会calloc()而是malloc(),因为您正在初始化浮点数或指针,并且您知道所有位都不是对他们而言必然意味着0。或者,您不需要额外的开销。
  • 如果您属于“需要时设置”阵营,则在分配某些数据并希望它为全零时,您可能需要calloc()。例如,如果您想计算n m动态分配的int数据的行总和。

1 你可以在这里查看我对许多问题的答案,看看我属于哪个阵营: - )。

答案 1 :(得分:8)

  1. 通过了解已存在的值,程序员可以采取一些快捷方式并进行某些优化。最常见的是calloc带有指针的结构:它们被初始化为NULL。
  2. 如果程序员忘记在分配中初始化某些内容怎么办?零是一个很好的默认值,而不是随机的东西。

  3. 在我很久以前工作的实时过程控制系统中,我们决定让开机逻辑将所有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 *函数,您可能希望 - 出于调试目的 - 使用通常不应出现的值填充缓冲区,但这将在分发时删除。

正如其他人所提到的,如果正在访问一个未初始化的变量,编译器会发出警告,因此我认为它的底线是没有理由初始化“以防万一。”