C语言 如果 nelem 或 elsize == 零,为什么 calloc 分配 1 个字节?



我正在努力开发四个基本内存分配例程mallocrealloccallocfree的调试实现(操作类似于 Electric Fence(,以调试嵌入式系统上的堆损坏,这些系统没有资源运行其他内存调试工具,或者不存在其他工具(例如, LynxOS 7.0 for PowerPC附带GCC 4.6.3,以及glibc和libstdc++的专有实现,其中不包括mtrace系列函数(。

以下是 calloc 的源代码,来自 GCC libiberty 中的 calloc.c。

PTR
calloc (size_t nelem, size_t elsize)
{
register PTR ptr;  
if (nelem == 0 || elsize == 0)
nelem = elsize = 1;
ptr = malloc (nelem * elsize);
if (ptr) bzero (ptr, nelem * elsize);
return ptr;
}

如果nelemelsize都等于0,为什么和都设置为等于1

如果我尝试分配大小为n0个块或大小n0块,这两种情况都会导致总字节数0而不是1字节的聚合分配吗?

是的,这只是糟糕的代码,这在libiberty/gnulib/等中并不意外。据我了解,如果malloc(0)每次调用返回一个空指针而不是唯一指针,他们已经替换了malloc,所以我看不出有任何充分的理由让calloc传递 1 到malloc而不是 0。此外,传递 1 中断/破坏调试工具,例如清理器,这些工具可以告诉您是否无意中取消了指向"零元素数组"的指针。

该代码也非常危险,因为它不检查乘法的溢出;要做到这一点,需要任何正确的calloc实现。

TL;大卫:这个代码是垃圾。

如果 nelem 或 elsize == 零,为什么 calloc 会分配 1 个字节?

减少歧义。

calloc(0, x), calloc(x, 0), malloc(0)成功后,可能会返回NULL或非NULL指针。 在这两种情况下,指针可能不会在不导致未定义行为(UB( 的情况下取消引用。

如果不成功,将返回NULL指针。

通过确保分配大小大于 0,返回NULL时没有歧义 -分配从此calloc()失败。


请注意,更好的功能还可以检测产品溢出。

if (nelem == 0 || elsize == 0) {
nelem = elsize = 1;
} else if (SIZE_MAX/nelem > elsize) {
return NULL;  // Too much for this implementation
}
...

关于Electric_Fence的进一步思考:

我希望该项目的malloc(0)也能确保不分配 0 字节。 然而,简单地调用ptr = malloc (0); if (ptr) bzero (ptr, 0);并不能将 1 个字节的分配归零。if (nelem == 0 || elsize == 0) nelem = elsize = 1;确保分配至少为 1 个字节,并且该分配为零。

相关内容

  • 没有找到相关文章