这些函数中的哪一个可能返回 1?
分配和释放突然停止工作
int foo1(size_t a) {
void *t = malloc(a);
if (t == NULL)
return 0;
while (1) {
free(t);
t = malloc(a);
if (t == NULL)
return 1;
}
}
无法重新定位,但成功重新定位
int foo2(size_t a, size_t b) {
void *t = malloc(a);
if (realloc(t, b))
return 0;
if (malloc(b))
return 1;
return 0;
}
既不是新的分配,也不是纯粹的扩展
int foo3(size_t a, size_t b) {
void *p, *q;
p = malloc(a);
if (malloc(b))
return 0;
q = realloc(p, b);
return p != q && q;
}
除了你没有包括<stdlib.h>
之外,没有令人信服的理由让foo1
最终失败并返回1
。对于任何给定的a
值,此函数的终止是特定于实现的。大多数系统最终会回收释放的块,并且永远不会重新分配a
字节,但是free
什么都不做的系统仍然符合标准,循环最终可能会失败。
函数foo2
会导致一个或多个内存泄漏。如果realloc()
失败,它将返回1
,但相同大小的malloc()
成功。 虽然这种情况会令人惊讶,但不能保证重新分配区块失败(或NULL
malloc(a)
失败(意味着下一次调用相同大小的malloc()
也应该失败。
函数foo3
具有潜在的未定义行为:不应在q = realloc(p, b)
后使用p
的值。如果块确实被重新分配,则p
的值可以成为陷阱值,因此不应将其与任何东西进行比较。 您可以通过将p
的值存储到unsigned char
数组中并在调用realloc
后比较字节值来解决此问题。然而,即使块没有移动,比较也可能会有所不同。似乎没有一种便携式方法来确定realloc()
是否移动了块。
然而,在p
不会成为陷阱值的系统上,确实有可能malloc(b)
失败并realloc(p, b)
成功并返回不同的地址:如果内存堆没有可用于malloc(b)
的块,malloc
将返回NULL
,但是如果p
之前有可用空间可以合并形成大小为b
的块,realloc
可能会成功并返回不同的地址。
所有这些测试都具有实现定义的行为。