用 c 分配内存,为什么普遍都是用 malloc 而不是用 calloc?

2019-06-10 21:31:30 +08:00
 africwildman

用 c 分配内存,为什么普遍都是用 malloc 而不是用 calloc ? calloc 会初始化为 0,更安全啊?《深入理解 c 指针》里,我记得也是 malloc 用的多。百度了一下,没看到比较好的解释。我是用 calloc。

8343 次点击
所在节点    C
23 条回复
junkun
2019-06-10 21:41:55 +08:00
实际应用中可能申请之后,就直接赋值或初始化了,或者今后会初始化(比如申请内存做栈,没使用的部分就未初始化)。calloc 直接赋值为 0,很可能是不必要的,尤其在申请空间较大的情况下,尤其是一些老的编译器可能不会做这样的优化。
zhuangzhuang1988
2019-06-10 22:01:45 +08:00
实际上你看开源的库都是有个自己 Memory 包装的
里面想怎么玩怎么玩
zmj1316
2019-06-10 22:13:04 +08:00
性能 填 0 也没什么意义
vs 里面 debug 下默认就是填 0xcc 更不容易搞错
pkookp8
2019-06-10 23:11:51 +08:00
我觉得大家学习的时候第一个接受到的是 malloc,并且被教导使用未初始化的内存是很危险的,这个可能也是一个原因,所以大家常用 malloc
malloc 是 memory alloction,也比较好记
平时看到代码中也有 malloc+memset 的写法,应该是写的人不知道 calloc 的功能
其实现代编译器和芯片不会真的因为 malloc+memset 改成 calloc 性能就上升一大截,如果是的话还是从考虑优化代码角度考虑
msg7086
2019-06-11 01:45:21 +08:00
甚至 memset 可以用优化过速度更快的版本。
kingcos
2019-06-11 01:54:10 +08:00
有同样的疑问。
autogen
2019-06-11 02:01:57 +08:00
所以才会有红红火火恍恍惚惚烫烫烫烫烫。。。。
wheeler
2019-06-11 08:01:43 +08:00
个人觉得主要是 0 字节作为的初始化的场景不是那么多。比如 NULL 指针,浮点数 0.0,C 标准都没有规定它们的底层表示是 0 字节。

https://stackoverflow.com/questions/1538420/difference-between-malloc-and-calloc

malloc 比 calloc 快也不一定对,这与实现有关系。

void *malloc(size_t size);
void *calloc(size_t nmemb, size_t size);

calloc 相对于 malloc 可能的一点好处是:
calloc 的函数原型是 nmem + member_size 的形式,而如果用 malloc 的话得:

malloc(nmem * member_size);

这时得考虑无符号乘法溢出的问题了,用 calloc 的话也不是一点问题没有,还是得看实现。见:

https://wiki.sei.cmu.edu/confluence/display/c/MEM07-C.+Ensure+that+the+arguments+to+calloc%28%29%2C+when+multiplied%2C+do+not+wrap
0x11901
2019-06-11 08:21:15 +08:00
书上和老师这么教的。
0x11901
2019-06-11 08:22:53 +08:00
@zmj1316 讲道理 calloc 相比 malloc memset 性能更高,但主要看编译器实现,理论上是一样的
pwrliang
2019-06-11 08:30:40 +08:00
我认为大多场景都是申请空间,然后灌满,再读取多次。主动填 0,会不会在大多数场景都影响性能?
urmyfaith
2019-06-11 08:55:57 +08:00
在需要填 0 的时候,就是用 calloc;

在不关系初始值,或者明确会覆盖的话,直接 malloc 不是更省操作.
urmyfaith
2019-06-11 08:57:31 +08:00
另外,很多人可能不知道有 calloc 这个东西.

导致 malloc + memset 或者 malloc + bzero 之类的.
xdeng
2019-06-11 09:22:21 +08:00
当你明确知道要用多大空间覆盖多少内容的时候,申请时去填 0 简直是多此一举。
zycpp
2019-06-11 10:23:49 +08:00
C 语言的大原则是程序员知道自己在干什么,
在这个前提下,也就没必要初始化了,
junkman
2019-06-11 10:32:20 +08:00
@wheeler 赞同

实际上,calloc 的实现在多数操作系统的实现和 malloc 几乎一样快,比如 Linux/FreeBSD 内核可能会直接返回 pre zero-mapped pages。

> You're likely to still see a performance improvement without overcommit. The OS will try to zero free pages in the background, so there's a good chance that it'll have pre-zeroed pages to hand you when you ask for them, rather than making you wait for them to be zeroed on demand.
Of course, there are plenty of systems where this doesn't happen, or there are no pages in the first place, or there's no kernel zeroing stuff for you.

回到问题本身,我觉得这个可能是历史原因,早期 calloc 作为一个库函数用于消除平台之间内存分配的差异,当初实现初始化零也是直接按字节填零操作的,可能是出于防御性编程的考虑(当时可能还没有这种概念),方便 debug。可能和 @wheeler 所说的类似,零内存使用场景并不大,而且清零还费时(当时机器性能可不如现在这么强大),malloc 孕育而生。大部分情况下申请内存之后我们都会填入一些数据,这样来看,使用 malloc 可以获得 performance agin。

> So the (slightly modified) question still stands: Why do calloc and malloc exist? Indeed it looks like calloc was originally intended as a portable way to allocate memory. It used the function alloc which apparently was not meant to be used directly; most iolib functions have a 'c' tacked on. So when iolib was reworked into the stdlib why was calloc kept? saretired suspects backward compatibility but I don't believe this, because no other c-prefixed iolib function was kept and i couldn't find any code that actually used calloc in the v6 distribution either. So maybe whoever is responsible for malloc/calloc in v7 (I think it was ken, not dmr) thought malloc should be a public function but saw a use for calloc and changed the semantics to be a bit more predictable.

see:
https://news.ycombinator.com/item?id=13108434

如果什么地方说的不对,麻烦指正。:-P
junkman
2019-06-11 10:33:28 +08:00
performance agin -> performance gain
xuddk727
2019-06-11 10:42:58 +08:00
做下位机开发的不知道什么情况,我只知道桌面开发一般都会有自己的内存分配策略,因为一些情况下可能得根据分页情况做性能优化,另一种是使用内存池,所以很少见,当然不是没有人用,不然何来屯屯屯屯屯屯和烫烫烫烫烫烫
africwildman
2019-06-11 11:14:55 +08:00
听了大家讨论,很受教啊。
wutiantong
2019-06-11 11:21:52 +08:00
@wheeler 感谢分享

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/572612

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX