开发者

Two arguments to calloc

开发者 https://www.devze.com 2023-01-23 19:50 出处:网络
Why does calloc take two arguments instead of one like malloc? Specifically, since there is no difference between (or is there?) between the following expressi开发者_开发技巧ons:

Why does calloc take two arguments instead of one like malloc?

Specifically, since there is no difference between (or is there?) between the following expressi开发者_开发技巧ons:

calloc (a, b);
calloc (b, a);
calloc (a * b, 1);
calloc (1, a * b);

why not just accept the total number of bytes to allocate? What is the rationale behind this interface? And why does this not apply to malloc?


I heard two [mutually exclusive] explanations for why it has two arguments:

  1. calloc takes the responsibility for checking for overflow on multiplication. If the total size of the requested block is too large (like overflows size_t), calloc returns null pointer to indicate failure. With malloc you have to watch for overflow yourself, which many people simply forget to do. (Although the history of standard library knows examples of calloc implementations that ignored overflow, and thus worked incorrectly).

  2. calloc actually allows one to allocate bigger blocks of memory than the range of type size_t, i.e. calloc might be capable of performing the proper non-overflowing large multiplication of its arguments and allocate the block of the resultant size. For this reason, since calloc uses two arguments of type size_t, it can allocate bigger blocks than malloc will ever be able to (since malloc takes only one argument of type size_t).

I always believed that the first explanation is the right one. However, after reading some posts here on SO I have my doubts.


I believe that malloc is guaranteed to return an area of memory which is aligned according to the coarsest requirement that would be compatible with the size indicated by the second argument. For example, if the system requires alignment of 2 and 4-byte integers, and the second argument is 10, the returned pointer must be aligned on a two-byte boundary; if the second argument were 12, the pointer would be aligned on a four-byte boundary. I suspect that in practice many systems will align all returned pointers to the largest possibly-required boundary, regardless of size, but I don't think it's required except for calloc.


The only notable difference is that calloc is required to initialize the allocated space to zeroes while there is no such guarantee with malloc. Otherwise, I guess there are two different functions just for historical reasons.


Everything is just bytes is a relatively new (ie c/Unix era) invention - on a lot of other architecture things were fixed sized records.


calloc(x,y) is a equivalent to malloc(x*y)

But calloc doing additional (setting values to 0 with) memset(block, 0, x*y)

This function is only for pretty way pass the size of element and number of elements, when in malloc you must multiply this values to get needed number of bytes, this function check integer overflow too in multiplication.

For example if you want allocate memory for 12 integers and you want do something with this integers and you must have setted her values to 0, use calloc(12, sizeof(int))

But if you want allocate some memory block (256 bytes) to copy in future to it some string then memset is a not usable for you, then better use is malloc(sizeof(char) * 256) or for example malloc(sizeof(wchar_t) * 256)


void *
calloc (size_t nmemb, size_t lsize)
{
  void *ptr;
  struct __meminfo *info;
  size_t size = lsize * nmemb;

  /* if size overflow occurs, then set errno to ENOMEM and return NULL */
  if (nmemb && lsize != (size / nmemb))
    {
      set_errno (ENOMEM);
      return NULL;
    }

  /* allocate memory */
  ptr = malloc (size);

  /* get pointer to info part of chunk */
  info = __mem2info (ptr);

  /* fill memory with zeros and set __MEM_CALLOC flag */
  memset (ptr, 0, info->size);
  info->flags |= __MEM_CALLOC;

  return ptr;                   /* happy end */
}
0

精彩评论

暂无评论...
验证码 换一张
取 消