5

What is the difference between calloc(10,4) and calloc(1,40)?

I see this behavior:

Thing** things = (Thing**)calloc(1, 10 * sizeof(Thing*));
// things[0] != 0

Thing** things = (Thing**)calloc(10, sizeof(Thing*));
// things[0] == 0

I would like to understand why. Edit: losing my mind is why, both seem to result in zero now... To at least make the question interesting, why doesn't calloc just take a single argument, like malloc?

NateS
  • 5,751
  • 4
  • 49
  • 59
  • +1; I've wondered this myself. I would like to know if it's exactly the same in all cases; i.e. does the standard mandate this? – Bathsheba Sep 26 '13 at 07:00
  • One (mildly useful) difference is that `calloc(n, sizeof(Thing))` allows you to allocate more than `SIZE_MAX` bytes, which is possible in theory. Whereas `n*sizeof(Thing)` can never be larger than `SIZE_MAX`. Therefore `calloc` can in theory be used to allocate more memory than `malloc` allows. – Lundin Sep 19 '19 at 14:40

4 Answers4

11

In practice it's the same. But there's one important feature this gives you.

Say that you're receiving some data from the network and the protocol has a field that specifies how many elements an array will contain that will be sent to you. You do something like:

uint32_t n = read_number_of_array_elements_from_network(conn);
struct element *el = malloc(n * sizeof(*el));
if (el == NULL)
    return -1;
read_array_elements_from_network(conn, el, n);

This looks harmless, doesn't it? Well, not so fast. The other side of the connection was evil and actually sent you a very large number as the number of elements so that the multiplication wrapped. Let's say that sizeof(*el) is 4 and the n is read as 2^30+1. The multiplication 2^30+1 * 4 wraps and the result becomes 4 and that's what you allocate while you've told your function to read 2^30+1 elements. The read_array_elements_from_network function will quickly overflow your allocated array.

Any decent implementation of calloc will have a check for overflow in that multiplication and will protect against this kind of attack (this error is very common).

S.S. Anne
  • 15,171
  • 8
  • 38
  • 76
Art
  • 19,807
  • 1
  • 34
  • 60
3

It is the same. The allocation does number of elements times size of one element to allocate the size.

It does not matter as it will be one block.

Samuel
  • 6,126
  • 35
  • 70
1

It's virtually the same, as the allocation block is contiguous. It allocates number_of_elements * size_of_element, so 10 elements of size 4 or 1 element of size 40 both end up allocating 40 bytes.

Marius Bancila
  • 16,053
  • 9
  • 49
  • 91
0

calloc(10,4) will allocate 10 no of elements where the size will be 4, whereas calloc(1,40) will allocated one elment with size of 40.

Ref : http://www.tutorialspoint.com/c_standard_library/c_function_calloc.htm

By size i mean for every element allocated.

Sunil Verma
  • 2,490
  • 1
  • 14
  • 15
  • In practice there's absolutely no difference, except for errors that may occur for very large numbers. – klutt Sep 15 '19 at 19:50