根据Linux手册页,calloc
和malloc
的区别在于malloc
不会初始化内存,而 calloc
确实初始化内存。
这在实践中意味着如果我创建一个像这样的结构:
struct Danger {
char a;
char b;
char c;
char d;
}
如果我使用 malloc
创建它:
struct Danger *dang = malloc(sizeof(struct Danger));
此时,dang->a
似乎确实可以是任何值,因为内存尚未初始化。如果我使用calloc
:
struct Danger *dang = calloc(1, sizeof(struct Danger));
我现在知道dang->a
必须等于\0
。
malloc
可能存在的原因是,您将立即写入已分配的整个内存空间,您一开始并不真正关心其中有什么。这可以节省您将无论如何都会被覆盖的数据归零的额外步骤
不过,从程序安全性和稳定性的角度来看,使用malloc
应该是异常(exception)而不是规则,因为它很容易导致未定义的行为。
两个问题:
- C 程序是否经常因
malloc
而处理意外的功能?这是一个相当频繁出现的问题吗? - 如果每次都使用
calloc
而不是malloc
,我真的会受到多少性能损失?
最佳答案
Do C programs in the wild deal with unexpected functionality as a result of malloc often? Is this a fairly recurrent problem?
他们经常处理“问题”,但通常采用的方式是尽量不读取垃圾数据。这通常没有问题,因为无论如何数据都需要初始化。真正的危险在于无意读取垃圾/零数据,这不能通过使用calloc()
来排除。
有一些方法可以确保程序不会读取垃圾数据。最简单的方法是使用 valgrind 执行测试套件。它报告任何垃圾数据的读取。它还会捕获任何释放后使用错误、未分配内存的访问、丢失的内存块等。
How much of a performance penalty do I really get if I just use
calloc
every time instead ofmalloc
?
正是两次写入数据的开销。它可能会从缓存中删除一些有值(value)的数据,因此这实际上取决于内存块有多大,以及您随后使用敏感数据填充它的操作顺序。
最坏的情况:清零会从缓存中逐出填充内存块所需的数据。这些数据需要从内存中重新加载,这是性能影响的主要部分。对于几兆字节数量级的内存块,这可能会产生大约 100 微秒的影响。详细信息取决于您的机器。
最好的情况:分配一个小内存块后立即填充它,而不读取任何数据。在这种情况下,开销只是将数据写入一级缓存的开销。尽管这是一个快速操作,但您仍然可以预期归零与您自己的初始化所花费的时间相同 - 缓存并不是无限快的。
就个人而言,当我需要零初始化 block 时,我仅使用calloc()
作为获取零初始化 block 的便捷方法。但通常情况并非如此。但这种情况时有发生。
关于c - malloc 相对于 calloc 的安全/性能影响?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25454358/