简体   繁体   中英

How much memory does calloc actually allocate?

The following code when tested, gives output as

1
0
0
2
0

which is amazing because ptr[3], ptr[4] did not have any memory allocation. Although they stored value in them and prints it. I tried the same code for few larger i's in ptr[i] which again compiled successfully and gives result but for very large value of i, of the order of 100000,program get crashed. if calloc() allocates such a large memory on single call then it is not worth effective. So how calloc() works? Where is this discrepancy?

#include <stdio.h>
void main() {
    int * ptr = (int *)calloc(3,sizeof(int));//allocates memory to 3 integer
    int i = 0;
    *ptr = 1;
    *(ptr+3) = 2;//although memory is not allocated but get initialized
    for( i =0 ; i<5 ; ++i){
        printf("%d\n",*ptr++);
    }
}

After that i tried this code which continuously runs without any output

#include <stdio.h>
void main() {
int * ptr = (int *)calloc(3,sizeof(int));
int i = 0;
*ptr = 1;
*(ptr+3) = 2;
//free(ptr+2);
for( ; ptr!=NULL ;)
{
    //printf("%d\n",*ptr++);
    i++;
}
printf("%d",i);
}

You are confounding two kinds of memory allocation: the kernel's and libc's.

When you ask malloc or calloc for 5 bytes, it does not turn around and ask the kernel for 5 bytes. That would take forever . Instead, the libc heap system obtains larger blocks of memory from the kernel, and subdivides it.

Therefore, when you ask for a small amount of memory, there is usually plenty of more accessible memory right after it that has not been allocated yet by libc, and you can access it. Of course, accessing it is an instant recipe for bugs.

The only time that referencing off the end will get a SIGnal is if you happen to be at the very end of the region acquired from the kernel.

I recommend that you try running your test case under valgrind for additional insight.

The code that you have has undefined behavior. However, you do not get a crash because malloc and calloc indeed often allocate more memory than you ask.

One way to tell how much memory you've got is to call realloc with increasing size, until the pointer that you get back is different from the original. Although the standard does not guarantee that this trick is going to work, very often it would produce a good result.

Here is how you can run this experiment:

int *ptr = calloc(1,sizeof(int));
// Prevent expansion of the original block
int *block = calloc(1, sizeof(int));
int *tmp;
int k = 1;
do {
    tmp = realloc(ptr, k*sizeof(int));
    k++;
} while (tmp == ptr);
printf("%d\n", k-1);

This prints 4 on my system and on ideone ( demo on ideone ). This means that when I requested 4 bytes (ie one sizeof(int) from calloc , I got enough space for 16 bytes (ie 4*sizeof(int) ). This does not mean that I can freely write up to four int s after requesting memory for a single int`, though: writing past the boundary of the requested memory is still undefined behavior.

calloc is allocating memory for 3 int 's in the given snippet. Actually you are accessing unallocated memory. Accessing unallocated memory invokes undefined behavior .

calloc allocates only the amount of memory that you asked, which in your case in for 3 int variables

but it doesnt create a bound on the pointer that it has created (in your case ptr). so you can access the unallocated memory just by incrementing the pointer. thats exactly whats happening in your case..

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM