【发布时间】:2021-05-12 15:19:17
【问题描述】:
假设我们有以下两段代码:
int *a = (int *)malloc(sizeof(*a));
int *b = (int *)malloc(sizeof(*b));
和
int *a = (int *)malloc(2 * sizeof(*a));
int *b = a + 1;
它们都在堆上分配了两个整数,并且(假设正常使用)它们应该是等价的。第一个似乎更慢,因为它调用 malloc 两次,并且可以产生对缓存更友好的代码。然而,第二个可能是不安全的,因为我们可以通过增加 a 并写入结果指针意外地覆盖 b 指向的值(或者恶意的人可以通过知道 a 的位置立即更改 b 的值)。
上述说法可能不正确(例如,此处质疑速度:Minimizing the amount of malloc() calls improves performance?)但我的问题是:编译器能否进行这种类型的转换,或者两者之间是否存在根本不同?标准?如果可能的话,哪些编译器标志(比如说 gcc)可以允许它?
【问题讨论】:
-
您应该指定哪种语言;我相信这两种情况的答案是不同的。
-
很有可能第二个 (double
malloc()) 片段使用的空间比第一个片段少。第一个需要两个大量的会计开销,所以在这种情况下a和b中的值相隔超过 4 个字节(在 32 位系统上可能至少相隔 8 个字节,并且在在 64 位系统上至少有 16 个字节,但这些数字可以通过不同的实现无休止地替代)。 -
您迫切需要养成使用
sizeof(int)的习惯,而不是假设4。像这样的代码使得从 32 位移植到 64 位远比应有的困难。 (当然,int的大小相同,但其他类型的大小差别很大。) -
试图欺骗优化器,后果自负。
-
这两个例子都可以写越界。两者都不安全。