4

The calloc function in C is used to allocate zeroed memory capable of holding at least the requested amount of elements of a specified size. In practice, most memory allocators may allocate a bigger block in order to increase efficiency and minimize fragmentation. The actual usable block size of an allocation in such systems is usually discoverable by means of special functions, i.e. _msize or malloc_usable_size.

Will calloc make sure the entire usable block is zeroed, or will it only zero the requested count*size part of the allocation?

klutt
  • 30,332
  • 17
  • 55
  • 95
Aiueiia
  • 162
  • 9
  • 10
    Why does it matter? You'll only be able to use the requested size, the remaining, if any, is not available to you anyways. – Sourav Ghosh Jul 11 '18 at 08:29
  • @SouravGhosh: The OP is asking about an extension in which the C implementation provides `malloc_usable_size` or similar function to report the usable size of the memory, which may be more than requested. In such an implementation, the amount reported as usable is usable, and the behavior of using it is defined. – Eric Postpischil Jul 11 '18 at 09:27
  • @Aiueiia: The behavior you ask about is dependent on the C implementation you use. You must specify which C implementation it is, such as a particular version of GCC, a compiler provided by a processor manufacturer, *et cetera*. – Eric Postpischil Jul 11 '18 at 09:33
  • 2
    Please read the documentation for `malloc_usable_size`: **The main use of this function is for debugging and introspection.** – Antti Haapala -- Слава Україні Jul 11 '18 at 09:51
  • @AndrewHenle: It is not “brain-damaged” to use an extension an implementation provides. If an implementation has allocated (and supports the use of) more memory than requested (due to the design of its memory management), and a program is able to make productive use of the additional memory, then it is fine for it to do so. – Eric Postpischil Jul 11 '18 at 10:25
  • 1
    @AndrewHenle: What you **need** and what you can **productively use** may be different things. A process might allocate space for caching purposes, for example. To do so, it may request some reasonable amount that will help it provide services efficiently. If the C implementation provides more, then using the additional space could further improve performance at no cost. – Eric Postpischil Jul 11 '18 at 10:30
  • @AndrewHenle I think that among those who uses functions like `malloc_usable_size` it is extremely few who does not understand that they are playing with fire. – klutt Jul 11 '18 at 10:49
  • @AndrewHenle: I have neither deleted your comments nor requested their deletion or flagged or reported them. As the issue is not about requesting less memory than is needed, your statement about requesting less memory than needed is irrrelevant. As for whether the benefit of using more memory may be worth losing some service of valgrind, it is certainly possible. – Eric Postpischil Jul 11 '18 at 10:50
  • Given that this question is asking about behaviour related to particular extensions offered by a particular (albeit not specified) compiler/library, the only way to get a definitive answer would be by referring to documentation for that compiler/library. In the C standard there is no guarantee that `calloc()` would reserve more memory than requested and, if it does so, no guarantee that such additional memory be initialised to zero. Practically, different compilers (or their libraries) do actually behave differently in this regard. – Peter Jul 11 '18 at 11:39
  • 1
    @Andrew Henle: You are wrong. The requested size is not the only usable memory. On compilers/libs that provide a way to determine the usable size of an allocation all of the returned size can safely be used by the program. And calling something "utterly brain-damaged", without even asking for the use-case is just plain rude. You are certainly mistaken about assuming that the required allocation size is known up-front: Many data structures rely on resizing buffers when they run out of space, and using the entire allocation might improve performance by avoiding some calls to realloc. – Aiueiia Jul 11 '18 at 12:24
  • @Aiueiia Are you sure that you *always* can safely assume such things? – klutt Jul 11 '18 at 19:19

3 Answers3

5

It's only guaranteed to zero out the requested allocation.

You should never rely on over-allocation.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • 1
    How do you know this? The OP is asking about a C implementation in which the implementation supports using more memory than requested if more was actually allocated, as reported by a function the implementation provides. That C implementation might also clear all the memory allocated by `calloc`, not just the requested amount. This question needs to be answered by reference to documentation of the C implementation, not the C standard. – Eric Postpischil Jul 11 '18 at 09:31
  • 2
    @EricPostpischil As an example, GNU libc only guarantees to zero out the requested allocation, as can be determined by examining its source code. – Ian Abbott Jul 11 '18 at 09:51
  • @IanAbbott That's the right thing to check, but it obviously doesn't give you the same long-term guarantee that a clear statement in the documentation would. (And, to be sure, even a clear statement in the documentation might be amended in a later version, also.) – Steve Summit Jul 11 '18 at 10:59
  • @SteveSummit I don't think a clear statement is warranted in this case. The documentation for `malloc_userable_size` already puts off the programmer from trying to make use of any extra space that the block contains. – Ian Abbott Jul 11 '18 at 16:49
  • @IanAbbott All I meant was that, in general, answering a question about an undocumented feature by peeking at the source code and saying "it is guaranteed..." is a risky proposition. :-) – Steve Summit Jul 11 '18 at 17:43
  • @SteveSummit But saying "it's only guaranteed [in some limited case covered by the standard]" is not risky. – Ian Abbott Jul 12 '18 at 09:30
5

Short answer: Without more information it's impossible to say, but I wouldn't count on it.

Longer answer:

If you ask for N bytes, the C Standard guarantees that (unless it fails) calloc will give you N bytes, and that they will all be 0. As far as the C standard is concerned, that's all we can say.

If you have a C library that (a) sometimes gives you more than N bytes and (b) gives you a well-defined way of finding out how many and (c) guarantees that it's permissible for you to use these extra bytes, we obviously can't say whether those bytes are guaranteed to be 0 or not. The C Standards don't tell us, and we don't know what C library you're using or what its special guarantees are.

Since it's your C library that might give you (a), (b), and (c), you're going to have to consult that particular library's documentation, source code, and/or author to answer the question (d) is any extra memory guaranteed to be 0? There is no universal, non-library-specific answer to this question.

Steve Summit
  • 45,437
  • 7
  • 70
  • 103
2

It depends on the implementation. The standard does not require it to zero more than the requested memory size.

The standard says:

Synopsis

#include <stdlib.h>
void *calloc(size_t nmemb, size_t size);

Description

The calloc function allocates space for an array of nmemb objects, each of whose size is size. The space is initialized to all bits zero.

I would say that it is pretty clear that this does not enforce zeroing anything except the space you have requested in the calloc call.

This is from an existing implementation:

PTR memset (PTR dest, register int val, register size_t len) {
  register unsigned char *ptr = (unsigned char*)dest;
  while (len-- > 0)
    *ptr++ = val;
  return dest;
}

void bzero (void *to, size_t count) {
  memset (to, 0, count);
}

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

It does only zero the memory you have requested. Other implementations may do it differently.

klutt
  • 30,332
  • 17
  • 55
  • 95