calloc - 将内存清零的有用性

chr*_*yal 11 c memory malloc memory-management calloc

将存储器清零(即calloc()结束malloc())的优点是什么?你不会将价值改为其他东西吗?

Alo*_*hal 16

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

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

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

现在有两个例外:

  • 如果你属于"初始化一切"阵营,你不这样做calloc(),但malloc()因为你是初始化浮点数字或指针,你知道,所有的位0并不一定意味着0他们.或者,您不需要额外的开销.
  • 如果你属于"需要时设置"阵营,你可能想要calloc()分配一些数据并希望它全部为零.举例来说,如果你要计算的的逐行总和n通过m动态分配的int数据.

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

  • 所有IEEE浮点格式定义"所有位零"的特殊情况表示真零. (3认同)
  • @Steve:出于安全原因,`brk()`或`sbrk()`系统调用(用于扩展内存分配的Linux系统调用)返回归零的内存。堆管理器从 sbrk() 请求额外的内存。但是,当本地分配释放某些内容时,堆管理器可能不会在后续分配之前将其清除 - 仅设置标头信息来管理它。 (2认同)

wal*_*lyk 8

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

在我很久以前工作的实时过程控制系统中,我们决定让上电逻辑将所有RAM初始化为0xCC(8086的interrupt 3指令).这将导致处理器进入监视器(原始调试器),如果它以某种方式执行未初始化的内存.(无益,8086快乐地执行包含零的内存,因为它们是add [bx+si],al指令.即使是32位模式也会使它们成为add [ax],al指令.)

我不记得我们是否曾找到失控程序,但是在各种值中对应于0xCC的值:52,428(无符号16位), - 19,660(带符号16位), - 107374176(32位浮点数)和-9.25596313493 e + 61(64位浮点)出现在许多意想不到的地方.此外,一些代码期望字符是7位ASCII - 也就是说,当它试图处理0xCC时,一个错误警告我们它的存在.

  • `(void*)0`不一定是全位零.编译器必须将`(void*)0`转换为适当的"空指针常量".类似地,当你写`p = 0;`和'p`是一个指针时,编译器必须将`p`设置为一个等于空指针常量的位模式,这可能不是所有的位零. (6认同)
  • calloc将指针设置为NULL是没有用的,因为标准不能保证all-bits-zero == NULL。对于浮点类似。 (2认同)
  • 自 20 世纪 70 年代末以来,情况并非如此。所有重要的体系结构都使用“(void *) 0”作为 NULL,并且 IEEE 浮点格式都使用“所有位为零”作为真零。 (2认同)
  • NULL的二进制表示不依赖于体系结构(AFAIK),而是编译器供应商的选择.我过去使用的旧Watcom C编译器(在x86上)表示带有0xffffffff的NULL指针. (2认同)