user13076787
user13076787

Reputation:

memory allocation for 0 elements with calloc()?

Actually I expected a warning / an error here but it compiles without any problems. Why is it possible to call a calloc-function with 0 objects as first argument? And why does it allocate memory for this?

int* p_integer=calloc(0, sizeof(int));

if(!p_integer){
    exit(EXIT_FAILURE); 
}

//prints 4 
printf("size *p_integer: %zu\n", sizeof(*p_integer));

OK, some additions:

void* calloc( size_t num, size_t size );


Allocates memory for an array of num objects of size and initializes all bytes in the 
allocated storage to zero.

If allocation succeeds, returns a pointer to the lowest (first) byte in the allocated 
memory block that is suitably aligned for any object type.

If size is zero, the behavior is implementation defined (null pointer may be returned, 
or some non-null pointer may be returned that may not be used to access storage) 

https://en.cppreference.com/w/c/memory/calloc

How to understand that? In my case is the size (second parameter) not zero, right? So there is no explanation for the case if the first parameter == zero. Or do I have to calculate 0*sizeof(int) == 0 (size of requested memory block). Which "size" do they mean?

Upvotes: 0

Views: 2989

Answers (3)

chux
chux

Reputation: 154169

Why is it possible to call a calloc-function with 0 objects as first argument? (OP)

It is possible because the C spec for the library says it is allowed. Yet memory allocations of 0 are an edge case that results in implementation-defined behavior.

C17/18 was recently updated in this area to:

If the size of the space requested is zero, the behavior is implementation-defined: either a null pointer is returned to indicate an error, or the behavior is as if the size were some nonzero value, except that the returned pointer shall not be used to access an object. C17dr § 7.22.3 1


And why does it allocate memory for this? (OP)

There is no evidence that any memory was allocated, just that a non-NULL pointer was returned for OP. It can't be used to reference any memory.

do I have to calculate 0*sizeof(int) == 0 (size of requested memory block). Which "size" do they mean?

The "size" is the product (without size_t range limitation). The size of an object is never 0 including sizeof(int), so only the n needs testing. With calloc(n, sz), where both are variables, I would test with if (n == 0 || sz == 0) rather than perform multiplication which brings in overflow issues.


To avoid this implementation defined behavior, test arguments first. Example:

int *p = (n > 0) ? calloc(n, sizeof *p) : malloc(1);
if (p == NULL) Oops();
...
free(p);

Alternatively, to account for implementation defined behavior, perhaps not error on calloc(0, sizeof *p) returning NULL.

int *p = calloc(n, sizeof *p);
if (p == NULL && n > 0) Oops();
...
free(p);

Upvotes: 2

Eric Postpischil
Eric Postpischil

Reputation: 223795

[This answer addresses the reason we would want calloc and malloc to provide zero bytes of memory when requested. It does not address what the C standard says about it.]

Consider writing a program that examines some input and perhaps categorizes various things, making lists of data in category C1, C2, and so on. Later, the software will process all the data for C1, then all the data for C2, and so on.

Consider which is simpler and shorter:

  • The program allocates space for N list items and processes N list items, and this code works whether N is zero or positive.
  • The program must explicitly test N and use different code paths depending on whether N is zero or positive.

The former choice is simpler, shorter, and cleaner. Generally, it offers less opportunity for bugs. When software must have different paths based on whether N is zero or positive, there is a chance a programmer might overlook the zero case, resulting in a bug.

Upvotes: 2

0___________
0___________

Reputation: 67835

zero sized malloc, calloc is 100% OK. free is OK

sizeof of the p_integer or *p_integer is not using dereferencing the pointer - it is 100% OK

you can assign any value to the p_integer - but if malloc or calloc returns valid not NULL pointer it will result in the potential memory leak;

Upvotes: 0

Related Questions