Why does calloc allocate 1 byte if nelem or elsize == zero?

梦想的初衷 提交于 2019-12-12 21:16:57

问题


I am working to develop debug implementations of the four basic memory allocation routines malloc, realloc, calloc, and free (similar in operation to Electric Fence) to debug heap corruption on embedded systems which do not have the resources to run other memory debugging tools, or for which other tools do not exist (for instance, LynxOS 7.0 for PowerPC ships with GCC 4.6.3, and a proprietary implementation of glibc and libstdc++ which does not include the mtrace family of functions).

The following is the source code for calloc, from calloc.c in GCC's libiberty.

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;
}

Why are nelem and elsize both set equal to 1 if either equals 0?

If I attempt to allocate 0 chunks of size n or n chunks with 0 size, wouldn't either case result in an aggregate allocation of 0 total bytes, and not 1 byte?


回答1:


Yes, this is just bad code, which is not unexpected from libiberty/gnulib/etc. As I understand it they already replace malloc if malloc(0) returns a null pointer rather than a unique pointer for each call, so I don't see any good reason for making calloc pass 1 to malloc instead of 0. Moreover, passing 1 breaks/undermines debugging tools like sanitizers that could tell you if you inadvertently dereferenced the pointer to a "zero-element array".

The code is also incredibly dangerous in that it does not check for overflow of the multiplication; any correct implementation of calloc is required to do this.

TL;DR: this code is junk.




回答2:


Why does calloc allocate 1 byte if nelem or elsize == zero?

To reduce ambiguity.

calloc(0, x), calloc(x, 0), malloc(0), when successful, may return NULL or a non-NULL pointer. In both cases, the pointer may not be de-referenced without causing undefined behavior (UB).

When unsuccessful, a NULL pointer is returned.

By insuring the allocation size is more than 0, there is no ambiguity when NULL is returned - the allocation failed from this calloc().


Note, a better function would also detect product overflow.

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

Further thought about Electric_Fence:

I'd expect the malloc(0) of that project to also insure that 0 bytes are not allocated. Yet simply calling ptr = malloc (0); if (ptr) bzero (ptr, 0); would not zero that 1 byte allocation. if (nelem == 0 || elsize == 0) nelem = elsize = 1; makes certain the allocation is at least 1 byte and that allocation is zeroed.



来源:https://stackoverflow.com/questions/58442295/why-does-calloc-allocate-1-byte-if-nelem-or-elsize-zero

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!